コンパイラが.RowsがDataRowsのコレクションを返すことを理解できないのはなぜですか?
DataTable Rows(DataRowCollection)が列挙型で機能する方法foreach
、および機能する方法とそのすべてがどれほど古いかと部分的に関係しているためです。
最初に少しforeach
:
foreach
実際には問題ではありません。これは、オブジェクトの列挙子を取得し、falseを返すまで、、、 ...を繰り返し呼び出す、whileループの言語ショートカットに似ています。このMoveNext
時点で、ループは停止します。whileのループ本体が最初に行うことは、列挙子を呼び出し、宣言で指定した変数に応答をロードすることです。作成したループの本体は、この最初のビットの後に、whileループの本体に配置されます。あなたにはそれは本当のループのように見えます。実際には、コンパイラによる検索/置換の演習のようなものです。C#の多くのことはこの方法です-新しい機能と構文の削減は、古い方法でコードを実行するための検索/置換方法にすぎません。MoveNext
MoveNext
MoveNext
Current
foreach
foreach
foreach
クラスがインターフェイスを実装したり、特定のタイプである必要がないようにするには、「列挙できるもの」を返すというメソッドが必要GetEnumerator()
です。
「列挙できるもの」bool MoveNext()
とは、「あらゆる種類のオブジェクトを返すメソッドとCurrent
プロパティを持つクラス」と定義されています。繰り返しますが、この「列挙できるもの」は、インターフェースを実装する必要はなく、特定のタイプである必要もありません。特定の名前と特定の署名を持つ1つのメソッドと1つのプロパティが必要です。全体が魔法のようなものであり、どこにも制約はありません。
public class ForeachableThing{
public EnumeratorSchmenumerator GetEnumerator(){
return new EnumeratorSchmenumerator();
}
}
public class EnumeratorSchmenumerator{
public DateTime Current {
get{ return DateTime.Now; }
}
public bool MoveNext() {
return DateTime.Now.Hour == 0;
}
}
これを何百万回も予測して、真夜中から午前1時までの現在の時刻を取得できます。列挙型は、コレクションを持っている必要も、どこかに移動する必要もありません。要求されたとおりに値を返し、移動するように指示されたときにtrueまたはfalseを返す必要があります。「しかし、確かに何かがIEnumerableを実装する必要があり、それはどこかに入力があることを意味します。」と思う場合に備えて、これについて概説します。いいえ-datatableが発明されて以来、特定のメソッド/プロパティがあるかどうかに基づいて純粋に物事を列挙することが可能になりました
にスキップしDataTable.Rows
ます; これはコレクションです。DataRowCollection
正確には。IEnumerable
を継承するという事実によってインターフェースをInternalDataCollectionBase
実装しますIEnumerable
が、それ自体は「クラスには「を返すメソッドが必要」を示すインターフェースでありGetEnumerator()
、「を強制するインターフェース」である必要があります。を返すプロパティと"を返すプロパティ。IEnumerator
IEnumerator
Current
object
MoveNext()
bool
可能にするためにこれらのインターフェースを実装する必要はありませんでしforeach
たが、それは役に立ちます。
..そして多分あなたはそれを見つけました:実装するにはプロパティが。でIEnumerator
ある必要がありますCurrent
object
これはコンパイラエラーです:
public class EnumeratorSchmenumerator : IEnumerator //look! new bit!
{
public DateTime Current {
get{ return DateTime.Now; }
}
public bool MoveNext() {
return DateTime.Now.Hour == 0;
}
}
'EnumeratorSchmenumerator'は、インターフェイスメンバー'IEnumerator.Current'を実装していません。[既存]'EnumeratorSchmenumerator.Current'は、'object'の一致する戻りタイプがないため、'IEnumerator.Current'を実装できません。
したがって、DataRowCollection
実装を選択する際に、を返すメソッドIEnumerable
を作成する必要があり、その結果、が強制的に.GetEnumerator()
IEnumerator
Current
object
そのオブジェクトのDataRow
内部にありますが、コンパイラはそれを認識していないため、var
asと入力しobject
ます。
foreach(DataRow r in dt.Rows)
C#が舞台裏で拡張するために書き込むコードを言うと、foreach
へのキャストが含まれDataRow
ます。
フォームで、var
あなたが書いたようなものですforeach(object r in dt.Rows)