比.ToArray()强大的东西强制枚举LINQ输出

我正在使用LINQ to objects并且有一个函数,在某些情况下我需要在调用Aggregate(...)之前修改底层集合,然后在函数返回Aggregate(...)的结果之前将其返回到其原始状态Aggregate(...) 我当前的代码看起来像这样:

 bool collectionModified = false; if(collectionNeedsModification) { modifyCollection(); collectionModified = true; } var aggregationResult = from a in (from b in collection where b.SatisfysCondition) .Aggregate(aggregationFunction) select a.NeededValue; if(collectionModified) modifyCollection(); return aggregationResult; 

但是,如上所述,如果我修改了集合,我将得到错误的结果,因为我在枚举aggregationResult并且延迟评估LINQ结果之前将集合恢复到其原始状态。 我目前的解决方案是在我的LINQ查询上使用.ToArray() ,如下所示:

 var aggregationResult = (from a in (from b in collection where b.SatisfysCondition) .Aggregate(aggregationFunction) select a.NeededValue).ToArray(); 

结果数组的大小总是很小(<100项),因此内存/处理时间不是问题。 这是处理我的问题的最佳方法,还是有更好的方法来强制评估LINQ查询?

只是为了检查我理解你 – 你基本上想要迭代所有的结果,只是为了强制发生任何副作用?

副作用通常是一个坏主意,因为这种逻辑更难理解。 话虽如此,最简单的方法并强制进行全面评估可能只是迭代它:

 foreach (var result in aggregationResult) { // Deliberately empty; simply forcing evaluation of the sequence. } 

或者,您可以使用LastOrDefault()来避免ToArray()中涉及的所有复制。 只要结果没有实现IList (涉及快捷方式), Count()就可以了。

(注意:在没有编译器的情况下键入,因此代码未经测试)

如果您已将.NET的Reactive Extensions作为依赖项,则可以使用Run():

 aggregationResult.Run(); 

但是可能不值得为此添加依赖项。

您也可以自己实现Run方法作为扩展方法:

 public static MyLinqExtensions { public static void Run(this IEnumerable e) { foreach (var _ in e); } } 

最好避免像上面的modifyCollection那样的副作用函数。

更好的方法是创建一个返回修改后的集合(或查询)的函数,让初始元素保持不变。

 var modifiedCollection = ModifyCollection(collection, collectionNeedsModification); var aggregationResult = from a in (from b in modifiedCollection where b.SatisfysCondition) .Aggregate(aggregationFunction) select a.NeededValue; 

其中ModifyCollection是一个方法,它根据collectionNeedsModification布尔参数返回参数中的修改后的集合(或查询)。

我不认为你的方法有问题,如果你总是使用结果(因为你的结果集不大,它不会消耗太多的内存。顺便说一句,如果你这样做,从不使用结果,它会造成性能损失)。 所以,是的,这是正确的方法。