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
(aT[][]
而不是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类型的值包装在一个结构中,该结构还包括变量名和日期时间戳。