File: DataView\SimpleRow.cs
Web Access
Project: src\src\Microsoft.ML.Data\Microsoft.ML.Data.csproj (Microsoft.ML.Data)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using Microsoft.ML.Internal.Utilities;
using Microsoft.ML.Runtime;
 
namespace Microsoft.ML.Data
{
    /// <summary>
    /// An implementation of <see cref="DataViewRow"/> that gets its <see cref="DataViewRow.Position"/>, <see cref="DataViewRow.Batch"/>,
    /// and <see cref="DataViewRow.GetIdGetter"/> from an input row. The constructor requires a schema and array of getter
    /// delegates. A <see langword="null"/> delegate indicates an inactive column. The delegates are assumed to be
    /// of the appropriate type (this does not validate the type).
    /// REVIEW: Should this validate that the delegates are of the appropriate type? It wouldn't be difficult
    /// to do so.
    /// </summary>
    [BestFriend]
    internal sealed class SimpleRow : WrappingRow
    {
        private readonly Delegate[] _getters;
        private readonly Action _disposer;
 
        public override DataViewSchema Schema { get; }
 
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="schema">The schema for the row.</param>
        /// <param name="input">The row that is being wrapped by this row, where our <see cref="DataViewRow.Position"/>,
        /// <see cref="DataViewRow.Batch"/>, <see cref="DataViewRow.GetIdGetter"/>.</param>
        /// <param name="getters">The collection of getter delegates, whose types should map those in a schema.
        /// If one of these is <see langword="null"/>, the corresponding column is considered inactive.</param>
        /// <param name="disposer">A method that, if non-null, will be called exactly once during
        /// <see cref="IDisposable.Dispose"/>, prior to disposing <paramref name="input"/>.</param>
        public SimpleRow(DataViewSchema schema, DataViewRow input, Delegate[] getters, Action disposer = null)
            : base(input)
        {
            Contracts.CheckValue(schema, nameof(schema));
            Contracts.CheckValue(input, nameof(input));
            Contracts.Check(Utils.Size(getters) == schema.Count);
            Contracts.CheckValueOrNull(disposer);
            Schema = schema;
            _getters = getters ?? new Delegate[0];
            _disposer = disposer;
        }
 
        protected override void DisposeCore(bool disposing)
        {
            if (disposing)
                _disposer?.Invoke();
        }
 
        public override ValueGetter<TValue> GetGetter<TValue>(DataViewSchema.Column column)
        {
            Contracts.CheckParam(column.Index < _getters.Length, nameof(column), "Invalid col value in GetGetter");
            Contracts.Check(IsColumnActive(column));
            if (_getters[column.Index] is ValueGetter<TValue> fn)
                return fn;
            throw Contracts.Except("Unexpected TValue in GetGetter");
        }
 
        /// <summary>
        /// Returns whether the given column is active in this row.
        /// </summary>
        public override bool IsColumnActive(DataViewSchema.Column column)
        {
            Contracts.Check(column.Index < _getters.Length);
            return _getters[column.Index] != null;
        }
    }
}