我正在使用LINQ to objects并且有一个函数,在某些情况下我需要在调用Aggregate(...)
之前修改底层集合,然后在函数返回{{{}}的结果之前将其返回到其原始状态。 1}}。我当前的代码看起来像这样:
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;
之前将集合恢复到其原始状态,并且LINQ结果是惰性评估的。我目前的解决方案是在我的LINQ查询中使用aggregationResult
,如下所示:
.ToArray()
结果数组的大小总是很小(<100项),因此内存/处理时间不是问题。这是处理我的问题的最佳方法,还是有更好的方法来强制评估LINQ查询?
答案 0 :(得分:15)
只是为了检查我理解你 - 你基本上想要遍历所有结果,只是为了强制发生任何副作用?
副作用通常是一个坏主意,因为这种逻辑很难理解。话虽如此,最简单的方法并强制进行全面评估可能只是迭代它:
foreach (var result in aggregationResult)
{
// Deliberately empty; simply forcing evaluation of the sequence.
}
或者,您可以使用LastOrDefault()来避免ToArray()中涉及的所有复制。只要结果没有实现IList<T>
(包含快捷方式),Count()就可以了。
答案 1 :(得分:13)
(注意:在没有编译器的情况下键入,因此代码未经测试)
如果您已将.NET的Reactive Extensions作为依赖项,则可以使用Run():
aggregationResult.Run();
但可能不值得为此添加依赖项。
您也可以自己实现Run方法作为扩展方法:
public static MyLinqExtensions
{
public static void Run<T>(this IEnumerable<T> e)
{
foreach (var _ in e);
}
}
答案 2 :(得分:3)
最好避免像上面的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布尔参数在参数中返回修改后的集合(或查询)。
答案 3 :(得分:0)
我不认为你的方法有问题,如果你总是使用结果(因为你的结果集不大,它不会消耗太多的内存。顺便说一下,如果你这样做,从来没有使用结果,它会造成性能损失)。 所以,是的,这是正确的方法。