foreach
ステートメントを扱うときにC#コンパイラを使用する"Pattern-based" approachをよく理解しています。なぜforeach文でC#コンパイラが文字列クラスを扱うのですか
およびC#言語仕様(セクション8.8.4)からは、すべてのC#コンパイラの最初GetEnumerator
方法を見つけようとするだけにしIEnumerable<T>
とIEnumerable
インターフェイスを見つけようとすることは明らかです。
しかし、なぜC#コンパイラの扱い別途string
、私のためにその不明確(String
クラスはCharEnumerator
を返し、それはまたIEnumerable<char>
とIEnumerable
interfcesを実装する方法GetEnumerator
が含まれているため):
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]);
しかし、私はString
クラスに関する言語仕様の例外を見つけることができません。誰かがこの解決策についていくつかの洞察を与えることができますか?
私はC#4コンパイラを試しました。前のコードスニペットのILコードは次のとおりです。
IL_0000: ldstr "1234"
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: stloc.2
IL_0008: ldc.i4.0
IL_0009: stloc.3
IL_000A: br.s IL_001E
IL_000C: ldloc.2
IL_000D: ldloc.3
IL_000E: callvirt System.String.get_Chars
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: call System.Console.WriteLine
IL_001A: ldloc.3
IL_001B: ldc.i4.1
IL_001C: add
IL_001D: stloc.3
IL_001E: ldloc.3
IL_001F: ldloc.2
IL_0020: callvirt System.String.get_Length
IL_0025: blt.s IL_000C
私の推測では、Stringクラス(またはいくつかのレガシーコード)の内部最適化だと思います。コンパイラをビルドするときは、内部クラスに必要な方法を選択できます。 – Sauleil