Ale*_*nov 12 c# linq ienumerable
假设我有一些代码:
var items = ItemsGetter.GetAllItems().Where(x => x.SomeProperty > 20);
int sum1 = items.Sum(x => x.SomeFlag == true);
Run Code Online (Sandbox Code Playgroud)
例如,我需要在代码后面的items集合中获得一些其他的总和.
int sum2 = items.Sum(x => x.OtherFlag == false);
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:可以IEnumerable不止一次调用Linq方法吗?也许我应该Reset()在枚举器上调用方法或使用ToList方法从项目中创建列表?
Jon*_*eet 22
嗯,这真的取决于你想做什么.您可以执行两次执行查询的命中(其确切含义取决于具体做法GetAllItems()),或者您可以将结果复制到列表:
var items = ItemsGetter.GetAllItems().Where(x => x.SomeProperty > 20).ToList();
Run Code Online (Sandbox Code Playgroud)
一旦它在列表中,显然多次迭代该列表不是问题.
请注意,你不能调用,Reset因为你没有迭代器 - 你有IEnumerable<T>.我不建议IEnumerator<T>总体上调用- 许多实现(包括由迭代器块中的C#编译器生成的任何实现)实际上并不实际实现Reset(即它们抛出异常).
我偶尔会遇到必须多次处理可枚举的情况。如果枚举代价高昂、不可重复并且会产生大量数据(例如从数据库读取的 IQueryable),则多次枚举不是一种选择,也不能将结果缓存在内存中。
直到今天,我经常最终编写聚合器类,我可以在 foreach 循环中将项目推入其中并最终读取结果 - 远不如 LINQ 优雅。
但是等等,我刚才说的是“推”吗?这听起来是不是……反应式?所以我在今晚散步的时候在想。回到家我试过了 - 它有效!
示例代码段展示了如何使用标准 LINQ 运算符(即 Rx 的运算符)在一次传递中从整数序列中获取最小和最大项:
public static MinMax GetMinMax(IEnumerable<int> source)
{
// convert source to an observable that does not enumerate (yet) when subscribed to
var connectable = source.ToObservable(Scheduler.Immediate).Publish();
// set up multiple consumers
var minimum = connectable.Min();
var maximum = connectable.Max();
// combine into final result
var final = minimum.CombineLatest(maximum, (min, max) => new MinMax { Min = min, Max = max });
// make final subscribe to consumers, which in turn subscribe to the connectable observable
var resultAsync = final.GetAwaiter();
// now that everybody is listening, enumerate!
connectable.Connect();
// result available now
return resultAsync.GetResult();
}
Run Code Online (Sandbox Code Playgroud)