C# 如何为实现IEnumerable的类实现GetEnumerator方法<;IEnumerable<;T>&燃气轮机;

C# 如何为实现IEnumerable的类实现GetEnumerator方法<;IEnumerable<;T>&燃气轮机;,c#,linq,ienumerable,C#,Linq,Ienumerable,背景: 我创建了一个通用的TimeSeries类,它应该实现IEnumerable接口: public interface ITimeSeries<T> : IEnumerable<IEnumerable<T>> { T[,] DataMatrix { get; } DateTime[] DateTime { get; } string[] Variables { get; } } public class TimeSeri

背景: 我创建了一个通用的
TimeSeries
类,它应该实现
IEnumerable
接口:

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();
    }
}
公共接口系统:IEnumerable
{
T[,]数据矩阵{get;}
DateTime[]DateTime{get;}
字符串[]变量{get;}
}
公共类时间序列:ITimeSeries
{
公共IEnumerator GetEnumerator()
{...}
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
}
TimeSeries
类“内部”实现为一个矩阵数据结构,每列表示一个不同的变量,每行表示一个观察值。另外还有一个表示时间轴的
DateTime[]
数组

首先,我希望能够使用
foreach
循环逐个变量迭代
TimeSeries
变量,并通过特定变量的所有观察值(使用内部
foreach
循环),但IEnumerable接口实现的实际原因是通过
IEnumerable
接口获得LINQ提供的所有功能,前提是我可以以某种方式确保每个观测的日期时间关联保持不变

那么对于这个问题:
我应该如何实现
GetEnumerator
方法来实现这一点?

最简单的方法就是循环遍历行并返回每行的值。我假设您按行的主要顺序存储,其中第一个维度是行,第二个维度是列。只需翻转下面的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;
    }
}
public IEnumerator GetEnumerator()
{
int rows=DataMatrix.GetLength(0);
int cols=DataMatrix.GetLength(1);
对于(int r=0;r

如果要避免复制,可以将其实现为
List
s的
List
Array
s的
Array
(a
T[][]
而不是
T[,]
).

我决定添加一个结构,它包装每个值,并添加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;
        }
    }
public结构TSItem
{
公共字符串变量{get;private set;}
公共日期时间日期{get;private set;}
公共T值{get;私有集;}
}
公共IEnumerator GetEnumerator()
{
int rows=DataMatrix.GetLength(0);
int cols=DataMatrix.GetLength(1);
for(int c=0;c

这可能不是最有效的解决方案,但在LINQ查询方面实现了我想要的功能。

StackOverflow
上查看[1]答案。[1] :我喜欢这个解决方案,但我主要担心的是,它会丢失每行的时间上下文以及按列过滤的功能。然而,问题不在于你的答案,而在于我的课堂设计。另一件事-使用T[,]而不是T[][]的原因是因为我的代码中其他地方的本机代码具有互操作性,但我建议使用thanx。是的,如果您的筛选器不是返回数据的一部分(例如,
timeSeries.Where),则尝试使用Linq时会遇到问题(dateI决定将T类型的值包装在一个结构中,该结构还包括变量名和日期时间戳。