简体   繁体   English

如何为实现IEnumerable的类实现GetEnumerator方法 <IEnumerable<T> &gt;

[英]How to Implement GetEnumerator method for class that implements IEnumerable<IEnumerable<T>>

BACKGROUND: I created a generic TimeSeries<T> class that should implement the IEnumerable<IEnumerable<T>> interface: 背景:我创建了一个通用的TimeSeries<T>类,它应该实现IEnumerable<IEnumerable<T>>接口:

public interface ITimeSeries<T> : IEnumerable<IEnumerable<T>> 
{
    T[,] DataMatrix { get; }  

    DateTime[] DateTime { get; }

    string[] Variables { get; }
}

public class TimeSeries<T> : ITimeSeries<T>
{
    public IEnumerator<IEnumerable<T>> GetEnumerator()
    {...}

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

The TimeSeries<T> class is 'internally' implemented as a matrix data structure with each column representing a different variable and each row an observation. TimeSeries<T>类是“内部”实现为矩阵数据结构,每列代表一个不同的变量,每一行代表一个观察。 There is also an additional DateTime[] array that represents the time axis. 还有一个表示时间轴的附加DateTime[]数组。

As a start I would like to be able to iterate through the TimeSeries<T> variable by variable with a foreach loop and also through all observations for a specific variable (with an inner foreach loop), but the actual reason for the IEnumerable interface implementation is to get all the features provided by LINQ through the IEnumerable interface, provided that I can somehow ensure that the DateTime association of each observation stays intact. 作为一个开始,我希望能够通过变量使用foreach循环遍历TimeSeries<T>变量,并通过所有对特定变量的观察(使用内部foreach循环),但是IEnumerable接口实现的实际原因是通过IEnumerable接口获取LINQ提供的所有功能,前提是我可以某种方式确保每个观察的DateTime关联保持不变。

So for the question: How should I go about to implement the GetEnumerator method to achieve this? 所以对于这个问题:我应该如何实现GetEnumerator方法来实现这一目标?

Simplest way is just to loop through the rows and return the values of each row. 最简单的方法是循环遍历行并返回每行的值。 I'm assuming you're storing in row-major order where the first dimension is the row and the second is the column. 我假设你以行主要顺序存储,其中第一个维度是行,第二个维度是列。 Just flip r and c below for column-major order: 只需按下列主要顺序的r和c:

public IEnumerator<IEnumerable<T>> GetEnumerator()
{
    int rows = DataMatrix.GetLength(0);
    int cols = DataMatrix.GetLength(1);

     for(int r = 0; r < rows; r++)
     {
        T[] row = new T[cols]();

        for(int c = 0; c < cols; c++)
        {
            row[c] = DataMatrix[r,c];
        }
        yield return row;
    }
}

If you want to avoid making a copy, you could implement it as either a List of List s or an Array of Array s (a T[][] instead of a T[,] ). 如果要避免复制,可以将其实现为List of ListArray of ArrayT[][]而不是T[,] )。

I've decided to add a struct which wraps each value and adds the DateTime stamp and Variable name properties and the GetEnumerator method yields a column of wrapped values: 我决定添加一个包装每个值的结构,并添加DateTime标记和变量名称属性,GetEnumerator方法生成一列包装值:

    public struct TSItem<T>
    {
        public string Variable { get; private set; }
        public DateTime Date { get; private set; }
        public T Value { get; private set; }
    }

    public IEnumerator<IEnumerable<TSItem<T>>> GetEnumerator()
    {
        int rows = DataMatrix.GetLength(0);
        int cols = DataMatrix.GetLength(1);

        for (int c = 0; c < cols; c++)
        {
            var col = new List<TSItem<T>>();

            for (int r = 0; r < rows; c++)
            {
                col.Add(new TSItem<T>(this.Variables[c], this.DateTime[r], 
                                DataMatrix[r, c]));
            }
            yield return col;
        }
    }

This is probably not the most performant solution, but achieves what I want in terms of LINQ queries. 这可能不是最高性能的解决方案,但在LINQ查询方面实现了我想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 动态生成的类,实现IEnumerator <T> GetEnumerator()和IEnumerator IEnumerable.GetEnumerator() - Dynamically generated class that implements IEnumerator<T> GetEnumerator() and IEnumerator IEnumerable.GetEnumerator() 模拟IEnumerable的GetEnumerator()方法 <T> 类型 - Mocking GetEnumerator() method of an IEnumerable<T> types IEnumerable的 <T> GetEnumerator()执行 - IEnumerable<T> GetEnumerator() exexcution 如何调用通用方法IEnumerator &lt;&gt; IEnumerable &lt;&gt;。GetEnumerator()? - how to call the generic method IEnumerator<> IEnumerable<>.GetEnumerator()? 如何在我的实现IEnumerable的Dictionary包装器类中实现IEnumerable <Foo> ? - How do I implement IEnumerable in my Dictionary wrapper class that implements IEnumerable<Foo>? 如果我只能定义一个GetEnumerator,为什么还要实现IEnumerable(T)? - Why implement IEnumerable(T) if I can just define ONE GetEnumerator? 用ienumerable实现ienumerable <T> - implement ienumerable with ienumerable<T> C#:你如何测试IEnumerable.GetEnumerator()方法? - C#: How do you test the IEnumerable.GetEnumerator() method? 如何序列化/反序列化实现IEnumerator,IEnumerable的类? - How to serialize/deserialze a class that implements IEnumerator, IEnumerable? 如何为实现 IEnumerable 的类创建解构器 - How to make a Deconstructor for class that implements IEnumerable
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM