代码Im维护有一个如下所示的常见模式,一个带有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#编译器是否发出类似于嵌套循环的代码,并且内部有一个if?
答案 0 :(得分:14)
实际上是否会创建更多对象,或者C#编译器是否会发出类似嵌套循环的代码,并且内部有一个if?
更多对象;每个LINQ操作(SelectMany
,Where
,Select
等)将生成一个新的占位符对象,该对象表示该操作的待处理IEnumerable<T>
查询,然后当它最后迭代,每个都会产生一个枚举器实例,以及上下文等。另外还有一个被提升的orderStorageId
等的捕获变量上下文。
请注意,常规foreach
也会产生枚举器实例,但foreach
的优点是它也可以使用鸭类枚举器 - 这意味着List<T>
之类的内容它实际上是使用struct
枚举器,而不是class
枚举器。当然,直接使用局部变量(orderStorageId
)(而不是匿名方法)意味着它不需要被提升到状态/上下文对象中。
所以是的,原始foreach
更直接,更有效率。有趣的问题是:区别重要。有时是,有时不是。