20

C# は初めてで、「var」の使用について質問があります

次のコードを使用すると、すべてがうまく機能します

foreach(DataGridViewRow row in myGrid.Rows)
{
    if (row.Cells[2].Value.ToString().Contains("51000"))
    {
        row.Cells[0].Value = "X";
    }
}

しかし、私がに変更DataGridViewRowするvarと、次のようなエラーが表示されます

「オブジェクト」には「セル」の定義が含まれておらず、「オブジェクト」型の最初の引数を受け入れる拡張メソッド「セル」が見つかりませんでした (using ディレクティブまたはアセンブリ参照がありませんか?)

4

4 に答える 4

28

myGrid.RowsタイプDataGridViewRowCollectionです。

これはかなり古いもので、その定義は次のとおりです。

public class DataGridViewRowCollection : ICollection, IEnumerable, IList

非汎用インターフェースが表示されますか? このクラスは実装でき、そのまま機能IList<DataGridViewRow>varますが、レガシーです。

IEnumerableアイテムタイプに関する情報を伝えません。関数は を返す可能性がありますが、 をGetEnumerator返すため、ここでは役に立ちません。IEnumeratorIEnumerator<DataGridViewRow>

基本的に、C# コンパイラは、関数とプロパティ (明示的に実装されている場合は/インターフェイス)GetEnumeratorを持つオブジェクトを返す関数を探します。このダックタイピングのアプローチは、歴史的な理由によるものであり、ジェネリックが言語に導入される前に存在していました。ループ変数は、プロパティと同じ型になります。そして(非ジェネリックバリアント) の中で、タイプはです。MoveNextCurrentIEnumerable<T>IEnumerableforeachCurrentIEnumeratorCurrentobject

タイプを明示的に指定する:

foreach (DataGridViewRow row in myGrid.Rows)

より良いメカニズムがないため、単に の戻り値を にキャストしますCurrentDataGridViewRow

ここでそのキーワードを本当に使用したい場合は、LINQ を使用して同じ効果を達成することもできます。var

foreach (var row in myGrid.Rows.Cast<DataGridViewRow>())

これは機能します。拡張メソッドが を返し、それが を利用し、最終的に列挙子のプロパティの型になるため、型情報が伝播されるからです。Enumerable.Cast<T> IEnumerable<T>IEnumerator<T>TCurrent

この時点でこれらの詳細が役立つとは思えませんが、この言語についてさらに学習する際に参照できるように保管しておくことをお勧めします。これを理解するには、拡張メソッドとジェネリック型について学ぶ必要があります。

于 2015-04-15T19:49:10.567 に答える
13

GridView.Rowsプロパティが型を返すためGridViewRowCollectionです。

この場合、オブジェクトが内部varになることを使用法から推測することはできません。DataGridViewRow

ソース: GridView.Rows プロパティ

于 2015-04-15T19:48:49.833 に答える
5

DataGridViewRow.RowsタイプはDataGridViewRowCollectionであり、実装されていませIEnumerable<DataGridViewRow>IEnumerable。そしてobject、キャストを指定しない場合にコンパイラが推測できる最良の推測DataGridViewRowですrow

于 2015-04-15T19:48:42.947 に答える