比.ToArray()更好的强制LINQ输出的枚举

时间:2008-11-24 13:13:04

标签: c# linq .net-3.5

我正在使用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查询?

4 个答案:

答案 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)

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