我清楚地理解在处理foreach
语句时使用C#编译器的"Pattern-based" approach。
从C#语言规范(第8.8.4节)可以看出,首先C#编译器尝试查找GetEnumerator
方法,然后才尝试查找IEnumerable<T>
和IEnumerable
接口
但我不清楚,为什么C#编译器会单独处理string
(因为String
类包含一个返回CharEnumerator
的方法GetEnumerator
,它也实现了{{1} }和IEnumerable<char>
interfces):
IEnumerable
转换为
string s = "1234";
foreach(char c in s)
Console.WriteLine(c);
但我在语言规范中找不到关于string s = "1234";
for(int i = 0; i < s.Length; i++)
Console.WriteLine(s[i]);
类的任何例外。有人可以就这个解决方案提供一些见解吗?
我尝试使用C#4编译器。以下是上一个代码段的IL代码:
String
答案 0 :(得分:21)
好抓。我知道编译器对数组执行了类似的优化,但我不知道它也是为字符串执行此操作。
我能得到的最好的是来自language specification的召唤,只要它产生相同的行为,就会使编译器有权偏离'canon':
8.8.4 foreach声明
[...]表格的foreach声明
foreach (V v in x)
嵌入式声明 然后扩展到:
{
E e = ((C)(x)).GetEnumerator();
try {
V v;
while (e.MoveNext()) {
v = (V)(T)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
[...] 允许实施 实施一个给定的foreach声明 不同的,例如为了表现 原因,只要是行为 与上述扩展一致。