2011-02-08 10 views
6

Powiel możliwe:
Why does var evaluate to System.Object in “foreach (var row in table.Rows)”?"var" typ wnioskowanie w C#

byłem dość zaskoczony odkrył następujące dzisiaj ....

SqlDataReader reader = cmd.ExecuteReader(); 
DataTable schemaTable = reader.GetSchemaTable(); 


// the following compiles correctly 
foreach (DataRow field in schemaTable.Rows) 
{ 
    Console.WriteLine(field["ColumnName"]); 
} 


// the following does not compile as 'var' is of type 'object' 
foreach (var field in schemaTable.Rows) 
{ 
    // Error: Cannot apply indexing with [] to an expression of type 'object' 
    Console.WriteLine(field["ColumnName"]); 
} 

Co słychać tutaj?

Czy to jest błąd wnioskowania typu? A jeśli tak, to co go powoduje?

Czy jest to część zdefiniowanego zachowania lub var? A jeśli tak, dlaczego?

Pomyślałem, że pomysł na var był taki, że można go używać wszędzie w zmiennej deklaracji/inicjalizacji bez zmiany zachowania.

+1

'DataRowCollection.GetEnumerator()' zwraca 'IEnumerator'. Typ 'IEnumerator.Current' to' object'. –

+0

[dokładne zduplikowane pytanie] (http://stackoverflow.com/questions/2325777/why-cant-i-do-foreach-var-item-in-datatable-rows) Zasadniczo Rows jest 'DataRowCollection', więc kompilator podnosi 'Obiekt', a nie' DataRow' – Axarydax

Odpowiedz

3

Punkt tutaj nie jest zmienny, ale pętla foreach. Pętla foreach może opcjonalnie odrzucić iterator dodatkowo do iteracji.

Więc można wykonać następujące czynności:

List<object> test = new List<object>(); 
test.Add(1); 
test.Add(2); 
test.Add(3); 
foreach(int i in test){ 
    i.Dump(); 
} 

Więc nawet jeśli lista jest typu obiektu, można rzutować na int w locie wewnątrz foreach.

+0

Nie wiedziałem tego, dzięki. Zastanawiam się, dlaczego iterator nie wymagał wyraźnej obsady w pierwszym przykładzie. – fearofawhackplanet

+0

Należy zauważyć, że jeśli to zrobisz, otrzymasz wyjątek odwołania zerowego, jeśli typ po lewej stronie nazwy zmiennej nie jest zgodny z rzeczywistym typem obiektu w wyliczeniu. Nie można go użyć, aby przejść do 'foreach (DerivedType pochodną w ListOfBaseTypes)' i oczekiwać, że działa poprawnie, chyba że wszystko w 'ListOfBaseTypes' jest typu' DerivedType' – Stephen

0

Zamieszanie polega na tym, że foreach(SomeType thing in SomeCollection) nie tylko dokonuje iteracji w kolekcji, ale także próbuje rzutować na SomeType dla każdego elementu podczas iteracji. Ale przy var nie ma nic do rzucenia.

1

DataTable.Rows zwraca System.Data.DataRowCollection, która jest podklasą InternalDataCollectionBase.

W tym przypadku wartość domyślna to IEnumerator, a nie IEnumerator<DataRows>.

Z tego powodu jedyną dostępną informacją o typie jest to, że zwraca ona object, więc po określeniu, że wymieniasz DataRow, dodajesz własną obsadę, której nie ma var.