Foreach,扩展方法和IEnumerable

时间:2018-03-27 16:18:13

标签: c# foreach extension-methods enumerable

出于好奇,这只是一个简单的问题。因此,根据有关foreach循环的MSDN文档,它实现了System.Collections.IEnumerable。在文档中还有一个警告,你在使用foreach循环时无法修改集合(我假设foreach循环在这方面不是非常安全的线程?)

文档https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/foreach-in

另外,出于好奇,在速度方面,foreach循环比for循环更优化吗?我知道foreach循环更容易输入/读取,但它的执行速度比for循环更快吗?

查看MSDN文档以获取列表,扩展方法Average是由Enumerable定义的。当文档说它对每个元素执行转换函数时,文档意味着什么? 这是否意味着扩展方法的行为类似于foreach循环? 文档https://msdn.microsoft.com/en-us/library/bb549067(v=vs.110).aspx

假设,假设我有两个主题。假设我有这两个线程共享的List。第一个线程遍历此列表(foreach),第二个线程使用此列表中的Average扩展方法。那么这会导致抛出异常吗?我知道使用锁可以避免任何潜在的问题,但为了讨论,我们假设我没有使用锁。

感谢您的时间。

1 个答案:

答案 0 :(得分:2)

  

因此,根据有关foreach循环的MSDN文档,它实现了System.Collections.IEnumerable

没有。支持GetEnumerator()方法的任何内容都会返回支持bool MoveNext()方法和Current属性的对象,并支持foreachIEnumerableIEnumerable<T>都支持这一点,因此实现它们的所有内容都允许foreach,但这不是唯一的方法。虽然这不仅是一种方便的方式,也是一种可以与IEnumerable<T>包含linq扩展方法的方法一起使用的方法,所以当你想支持foreach时,通常最好采用这种方法。 。 (您可以选择支持List<T>之类的其他方法,但它很少值得。)

  

另外,出于好奇,在速度方面,foreach循环比for循环更优化吗?

这很复杂,因为foreach关于什么与for的关系是forforeach通常具有优势,因为它涉及少量虚拟调用,但foreach更快时会有例外情况。如果您直接在一个数组上执行操作会增加复杂性,那么for会慢一些,除非编译器实际捕获它并在后面将它重写为Average,因此它们完全相同。

  

当文档说它对每个元素执行转换函数时,文档意味着什么。

这意味着selector的特定重载会将每个元素传递给传递给它的foreach。这是转换的平均结果。

  

这是否意味着扩展方法的行为类似于foreach循环?

是。实际上,它们通常是foreach。该特定方法是.NET Framework版本中的foreach,并且在.NET Core版本中对foreach进行了轻微优化。两个版本中的许多方法都是for。有些方法在少数情况下使用foreach,其中已知其性能更高(参见上文有关情况有时如何,有时则不然)。在绝大多数情况下,所做的大部分优化都不值得,但Linq方法被很多人大量使用,因此优化甚至一点点的努力都会得到回报。

  

第一个线程遍历此列表(foreach),第二个线程使用此列表中的Average扩展方法。那么这会导致抛出异常吗?

在这种特殊情况下,只要没有线程写入列表,两者就不会导致彼此出现任何问题。用于实现List<T>的对象是在每个线程中单独创建的,它们是唯一的变异对象。 foreach的文档无法保证这一点,但不太可能改变。

但这并不适用于支持foreach的所有内容。除了给定的实现方式之外,多线程...没有任何承诺。