有人能指出C#
语句和它们相似的扩展方法之间的区别吗?例如:foreach
与.ForEach
(扩展方法)。
如果存在任何差异,它们是什么?安全方面?性能方面?哪一个更好用?哪一个更安全?等
如果没有差异,为什么还要写呢?
我一直在思考和搜索这个问题,如果是我的问题,但没有找到我的答案。
这取决于您使用的扩展方法的实现。在内部,大多数版本的.ForEach.并没有什么特别之处
在应用程序加载和编译时加载扩展方法的时间最短/可以忽略。将.ForEach语法转换为底层ForEach"可能"开销最小,因为它在技术上只是一个包装器。它可能会导致安全问题,但这只是因为它可能会创建关闭位置,在该位置,您的对象可能无法在预期时间收集(例如:在作用域中保存的时间更长)。最终,差别非常非常小,归根结底是味道。当然,除非你试图每一毫秒都剃光,在这种情况下,使用原生身体是最好的方法。
我想提到的是,.ForEach违背了使用lambda语句是纯函数的前提,也就是说,它打破了"函数"风格,并引入了副作用的可能性。使用foreach主体使代码更加可读和明确。
请参阅:为什么IEnumerable上没有ForEach扩展方法?
这是一种折衷。扩展方法当然更简洁,而且它提供了编译时检查。扩展方法还可能带来可读性困难、可维护性困难和副作用。
从这里拍摄
第二个原因是这样做不会增加新的表示语言的力量。这样做可以让你完美地重写清除代码:
foreach(Foo中的Foo){涉及Foo的语句;}
转换为此代码:
foos.ForEach((Foo-Foo)=>{涉及Foo的语句;});
它使用几乎完全相同的字符,但略有不同顺序然而,第二个版本更难理解,更难理解调试,并引入闭包语义,从而可能发生更改对象以微妙的方式生存。
提供的答案不准确。使用ForEach
扩展方法时存在许多陷阱。例如,以下扩展方法可能很容易成为性能杀手:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
}
}
然后我们滥用它:
IEnumerable<T> items = new List<T>();
items.ForEach(UpdateItem);
看起来不错,对吧?这里,ForEach()
扩展方法是在IEnumerable<T>
上调用的,这意味着编译器被迫分配一个泛型枚举器,而不是使用优化的、无分配的版本。然后,Action
参数调用另一个相当重的委托分配。将此循环置于热路径上,Garbage Collector
将发疯,从而导致严重的性能问题。
请看我的另一个答案,我在其中更详细地解释了这一点。
在安全性方面,我看到开发人员意外地包含了一个第三方程序集来使用特定的ForEach()
扩展方法。这意味着从不知从何处以未知的能力运送不需要的依赖。
摘要
foreach
更安全- CCD_ 11的性能更强
- CCD_ 12较好。编译器确切地知道如何有效地处理它
.ForEach
类似于Parallel.ForEach
。我以前见过用于开发/调试并行版本的常规.ForEach
。它的好处在于,你不必更改一堆代码来在两者之间移动。
一般来说,如果我不想做Parallel.ForEach
,那么为了可读性,我更喜欢常规的foreach
。