ここで説明する内容は、C# 言語仕様のセクション「foreach ステートメント」で正式に詳細に説明されています。
暗黙的に型指定された反復変数をforeachステートメント (つまり) で使用する場合var、これは非常に良いことですが、コンパイラがvar意味するものを見つける方法は次のとおりです。
最初に、 のキーワードの右側にある式のコンパイル時の型をチェックします。(または類似の配列型の場合は、特別な規則が適用されます。それが の場合は、別の規則があります。)inforeachPropertyDescriptor[]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なっています。intSystem.Int32Current
あなたの場合、コンパイル時のタイプpropsはPropertyDescriptorCollection. この型には、GetEnumerator()必要に応じてパブリックで非静的な があります。メソッドの戻り値の型は、System.Collections.IEnumeratorこの場合に見られます。このIEnumeratorタイプには必要なCurrentプロパティがあり、このプロパティのタイプは であることがわかりますObject。だからそこから来ました!
(元は .NET 1 用に作成された多くのクラスがこの設計を持っています。強い型付けはありませんforeach。)
型が(ジェネリック) or/and (非ジェネリック) を実装し、これら 2 つのインターフェイスのいずれかが「暗黙的に」実装されている場合 (通常は、明示的なインターフェイスの実装ではありません)、その型には確実にpublic であり非公開の があることに注意してください。-static、非ジェネリック、引数なし。その public メソッドは によって使用されます。IEnumerable<out T>IEnumerableGetEnumeratorforeach
しようとしている式のコンパイル時の型にforeachパブリック インスタンス メソッドがない場合GetEnumerator()(型パラメーターも値パラメーターもありません)、コンパイラは型がIEnumerable<Something>or (else) に変換可能かどうかを確認しIEnumerableます。IEnumerable<out T>は で共変であるため、T多くの場合、多くの場合に適用されます。これは、仕様 (バージョン 5.0) で少し紛らわしく説明されています。タイプが次のようになる可能性もあります。SomethingIEnumerable<Something>
class Foreachable : IEnumerable<Animal>, IEnumerable<Giraffe>
{
// lots of stuff goes here
}
参照型AnimalとGiraffe予想される継承関係の場合、仕様バージョン 5.0から、このクラス (コンパイル時の型) をforeach編集できないことが明確ではありません。