我维护的代码有一个像下面这样的常见模式,一个嵌套循环,用 if 来查找某些元素。

        foreach (Storage storage in mStorage.Values)
            foreach (OrderStorage oStorage in storage.OrderStorage)
                if (oStorage.OrderStorageId == orderStorageId)

我想把它改成 LINQ:
        foreach (OrderStorage oStorage in (from storage in mStorage.Values
                                           from oStorage in storage.OrderStorage
                                           where oStorage.OrderStorageId == orderStorageId
                                           select oStorage))

但这似乎并没有那么吸引人,因为这里发生的事情不太透明,可能会创建更多的对象,从而在内存和 CPU 方面造成性能损失。实际上是否会创建更多对象,或者 C# 编译器是否会发出类似于嵌套循环的代码?

最佳答案



更多对象;每个 LINQ 操作( SelectManyWhereSelect 等)将产生一个新的占位符对象,表示该操作的待处理 IEnumerable<T> 查询,然后当它最终被迭代时,每个操作都会产生一个枚举器实例,以及上下文等。另外还有一个用于提升的 orderStorageId 等的捕获变量上下文。

请注意,常规 foreach 也会产生枚举器实例,但 foreach 的优点是它也可以使用鸭子类型的枚举器——这意味着对于 List<T> 之类的东西,它实际上使用的是 struct 枚举器,而不是 class 枚举器。当然,直接使用局部变量( orderStorageId )(而不是匿名方法)意味着它不需要被提升到状态/上下文对象中。

所以是的,原始的 foreach 更加直接和高效。有趣的问题是:差异是否重要。有时是,有时不是。

10-06 13:27