为什么在C#中基于模式的编程

Con*_*der 8 c# foreach iterator

想知道为什么C#正朝着更多基于模式的编程而不是传统方式发展.

防爆.该foreach声明预计,循环源已经被称为魔术方法GetEnumerator,它返回它有几个魔术方法类似于对象MoveNextCurrent,但他们并没有强制任何特定的接口?C#可以强制要求使用的类foreach应该实现,IEnumerable或者IEnumerable<T>using语句执行,因为它期望在using语句中使用对象来实现IDisposable接口.

此外,我看到async/ await关键字也有类似的趋势....

当然必须有一个很好的理由,但是我理解编译器/ CLR需要"魔术方法"而不是依赖接口的原因似乎有点奇怪.

Mar*_*zek 12

foreach

我会说这是关于性能和兼容性的

  • 如果你选择foreach使用IEnumerable它会使得所有泛型集合迭代对于值类型来说非常慢T(因为装箱/取消装箱).
  • 如果您选择使用IEnumerable<T>迭代ArrayList,那么早期.NET版本的所有非泛型集合都是不可能的.

我认为设计决定很好.何时foreach推出(.NET 1.1),.NET中的泛型(它们是在.NET 2.0中引入)并不存在.选择枚举IEnumerable的来源foreach会使得它与通用集合的使用不佳或需要彻底改变.我想设计师已经知道他们将在很久以后推出仿制药.

Additionaly,宣称它作为使用IEnumerable<T>时,它的可用或IEnumerable当它不没有太大的不同,然后利用现有的GetEnumerator方法或当它不可用,不进行编译,是吗?

更新

正如@mikez在评论中提到的那样,还有一个优点.如果您不希望GetEnumerator返回IEnumerator/ IEnumerator<T>您可以返回struct并且在循环使用枚举器时不必担心装箱.

LINQ

使用LINQ和基于语法的查询时会出现相同的魔术方法情况.当你写作

var results = from item in source
              where item != "test"
              select item.ToLower();
Run Code Online (Sandbox Code Playgroud)

它由编译器转换为

var results = source.Where(x => x != "test")
                    .Select(x => x.ToLower());
Run Code Online (Sandbox Code Playgroud)

并且因为无论什么接口source实现,该代码都可以工作,这同样适用于基于语法的查询.只要将其转换为基于方法的查询,每个方法调用都可以通过编译器正确分配,一切正常.

异步/ AWAIT

我不是那么肯定,但认为同样的事情适用于async/ await.当您使用这些关键字时,编译器会为您自己生成一堆代码,然后将其编译为您自己编写代码.只要可以编译由该转换生成的代码,一切都可以.