想知道为什么C#正朝着更多基于模式的编程而不是传统方式发展。
实施例。 foreach
语句要求循环源有一个名为GetEnumerator
的魔术方法,该方法返回一个对象,该对象具有更多魔法方法,如MoveNext
和Current
,但它们不会不要求任何特定的界面? C#可能要求foreach
中使用的类应该像IEnumerable
语句一样实现IEnumerable<T>
或using
,因为它期望在using
语句中使用对象实现IDisposable
接口的async
语句。
另外,我也看到了与await
/ {{1}}个关键字类似的趋势....
当然必须有一个很好的理由,但对于我来说理解编译器/ CLR需要“魔术方法”而不是依赖接口的原因似乎有点奇怪。
答案 0 :(得分:12)
的 foreach
强> 的
我会说这是关于性能和兼容性的
foreach
来使用IEnumerable
,那么它就会变得非常通用
对于值类型T
,集合迭代非常慢(因为
装箱/拆箱)。IEnumerable<T>
迭代ArrayList
和。{
来自早期.NET版本的所有非泛型集合都不会
可能的。我认为设计决定很好。当引入foreach
(.NET 1.1)时,.NET中的泛型(它们是在.NET 2.0中引入的)中没有任何内容。选择IEnumerable
作为foreach
枚举的来源会使得它与通用集合使用不佳或需要彻底改变。我想设计师已经知道他们将在很久以后推出仿制药。
另外,在可用时将其声明为使用IEnumerable<T>
,或者当它不是时将其声明为IEnumerable
与使用可用的GetEnumerator
方法或当它不可用时不编译,是吗?
更新
正如@mikez在评论中提到的,还有一个优势。如果您不希望GetEnumerator
返回IEnumerator
/ IEnumerator<T>
,则可以返回struct
,并且在循环使用枚举数时不要担心装箱。
的 LINQ 强> 的
使用基于LINQ和语法的查询时会出现相同的魔术方法情况。当你写
var results = from item in source
where item != "test"
select item.ToLower();
它被编译器转换为
var results = source.Where(x => x != "test")
.Select(x => x.ToLower());
并且因为无论什么接口source
实现,该代码都可以工作,这同样适用于基于语法的查询。只要将其转换为基于方法的查询,每个方法调用都可以由编译器正确分配,一切正常。
的异步/ AWAIT 强> 的
我不确定,但认为同样的事情适用于async
/ await
。当您使用这些关键字时,编译器会为您自己生成一堆代码,然后将其编译为您自己编写代码。只要可以编译由该转换生成的代码,一切都可以。