31

私が次のことができない理由はありますか?

foreach (var Item in DataTable.Rows) {

する必要はなく

foreach (DataRow Item in DataTable.Rows) {

他のデータ型と同じように、これは可能だと思いました。例えば:

foreach (var Employee in Staff) { // string[] Staff etc...

最初のforeachループを試すと、エラーCS0021:[]を使用したインデックスを'object'型の式に適用できません

コンパイラが.RowsがDataRowsのコレクションを返すことを理解できないのはなぜですか?

4

3 に答える 3

30

RowsIEnumerable効果的に( )を返すため、コンパイラは。の型としてDataRowCollectionのみ選択できます。を使用したい場合に使用します。objectvarRows.Cast<DataRow>var

CastはEnumerableで定義されているため、System.Linqを含める必要があります。

于 2010-02-24T12:09:20.443 に答える
24

ブライアンはこの理由について完全に正しいですが、それを回避するより簡単な方法があります:DataTableExtensions.AsEnumerable()を使用してください:

foreach (var row in DataTable.AsEnumerable())
{
    ...
}
于 2010-02-24T12:10:07.703 に答える
2

コンパイラが.RowsがDataRowsのコレクションを返すことを理解できないのはなぜですか?

DataTable Rows(DataRowCollection)が列挙型で機能する方法foreach、および機能する方法とそのすべてがどれほど古いかと部分的に関係しているためです。

最初に少しforeach

foreach実際には問題ではありません。これは、オブジェクトの列挙子を取得し、falseを返すまで、、、 ...を繰り返し呼び出す、whileループの言語ショートカットに似ています。このMoveNext時点で、ループは停止します。whileのループ本体が最初に行うことは、列挙子を呼び出し、宣言で指定した変数に応答をロードすることです。作成したループの本体は、この最初のビットの後に、whileループの本体に配置されます。あなたにはそれは本当のループのように見えます。実際には、コンパイラによる検索/置換の演習のようなものです。C#の多くのことはこの方法です-新しい機能と構文の削減は、古い方法でコードを実行するための検索/置換方法にすぎません。MoveNextMoveNextMoveNextCurrentforeachforeach

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()、「を強制するインターフェース」である必要があります。を返すプロパティと"を返すプロパティ。IEnumeratorIEnumeratorCurrentobjectMoveNext()bool

可能にするためにこれらのインターフェースを実装する必要はありませんでしforeachたが、それは役に立ちます。

..そして多分あなたはそれを見つけました:実装するにはプロパティが。でIEnumeratorある必要がありますCurrentobject

これはコンパイラエラーです:

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()IEnumeratorCurrentobject

そのオブジェクトのDataRow内部にありますが、コンパイラはそれを認識していないため、varasと入力しobjectます。

foreach(DataRow r in dt.Rows)C#が舞台裏で拡張するために書き込むコードを言うと、foreachへのキャストが含まれDataRowます。

フォームで、varあなたが書いたようなものですforeach(object r in dt.Rows)

于 2020-07-08T11:02:17.160 に答える