ここで説明する内容は、C# 言語仕様のセクション「foreach ステートメント」で正式に詳細に説明されています。
暗黙的に型指定された反復変数をforeach
ステートメント (つまり) で使用する場合var
、これは非常に良いことですが、コンパイラがvar
意味するものを見つける方法は次のとおりです。
最初に、 のキーワードの右側にある式のコンパイル時の型をチェックします。(または類似の配列型の場合は、特別な規則が適用されます。それが の場合は、別の規則があります。)in
foreach
PropertyDescriptor[]
PropertyDescriptor[,,,]
dynamic
その型に、非静的、非ジェネリックであり、ゼロのパラメーターをGetEnumerator
受け取るオーバーロードを使用して (その大文字化で)正確に呼び出されるメソッドがあるかどうかを確認します。public
そうであれば、このメソッドの戻り値の型を調べます (ここではまだコンパイル時の型について話しているので、宣言された戻り値の型です)。この型には、メソッドMoveNext()
とプロパティが必要Current
です。次に、プロパティ タイプを受け取り、それを要素タイプCurrent
として使用します。したがって、あなたはこのタイプの略です。var
これがどのように機能するかを示すために、私はこれを書きました:
class Foreachable
{
public MyEnumeratorType GetEnumerator() // OK, public, non-static, non-generic, zero arguments
{
return default(MyEnumeratorType);
}
}
struct MyEnumeratorType
{
public int Current
{
get { return 42; }
}
public bool MoveNext()
{
return true;
}
}
static class Test
{
static void Main()
{
var coll = new Foreachable();
foreach (var x in coll) // mouse-over 'var' to see it translates to 'int'
{
Console.WriteLine(x);
}
}
}
私の場合は、プロパティのタイプにより( ) にvar
なっています。int
System.Int32
Current
あなたの場合、コンパイル時のタイプprops
はPropertyDescriptorCollection
. この型には、GetEnumerator()
必要に応じてパブリックで非静的な があります。メソッドの戻り値の型は、System.Collections.IEnumerator
この場合に見られます。このIEnumerator
タイプには必要なCurrent
プロパティがあり、このプロパティのタイプは であることがわかりますObject
。だからそこから来ました!
(元は .NET 1 用に作成された多くのクラスがこの設計を持っています。強い型付けはありませんforeach
。)
型が(ジェネリック) or/and (非ジェネリック) を実装し、これら 2 つのインターフェイスのいずれかが「暗黙的に」実装されている場合 (通常は、明示的なインターフェイスの実装ではありません)、その型には確実にpublic であり非公開の があることに注意してください。-static、非ジェネリック、引数なし。その public メソッドは によって使用されます。IEnumerable<out T>
IEnumerable
GetEnumerator
foreach
しようとしている式のコンパイル時の型にforeach
パブリック インスタンス メソッドがない場合GetEnumerator()
(型パラメーターも値パラメーターもありません)、コンパイラは型がIEnumerable<Something>
or (else) に変換可能かどうかを確認しIEnumerable
ます。IEnumerable<out T>
は で共変であるため、T
多くの場合、多くの場合に適用されます。これは、仕様 (バージョン 5.0) で少し紛らわしく説明されています。タイプが次のようになる可能性もあります。Something
IEnumerable<Something>
class Foreachable : IEnumerable<Animal>, IEnumerable<Giraffe>
{
// lots of stuff goes here
}
参照型Animal
とGiraffe
予想される継承関係の場合、仕様バージョン 5.0から、このクラス (コンパイル時の型) をforeach
編集できないことが明確ではありません。