2011-08-08 17 views
7

Este código funciona:¿Por qué no funciona este elenco?

foreach(DataColumn column in table.Columns) 
{ 
    // do whatever 
} 

Pero este código no:

(IEnumerable<DataColumn>)(table.Columns) 

La propiedad .Columns devuelve un DataColumnCollection que es un InternalDataCollectionBase, que implementa IEnumerable, así que debería funcionar.

El error que consigo es

No se puede convertir tipo 'System.Data.DataColumnCollection' a 'System.Collections.Generic.IEnumerable'

Respuesta

19

DataColumnCollection implementa IEnumerable, y cada fila devuelta es a DataColumn, pero no implementa IEnumerable<DataColumn>. Como no implementa la interfaz, no se puede convertir a la interfaz. A medida que la clase está sellada, el compilador sabe que el valor no puede implementar la interfaz, por lo que ni siquiera puede convertirlo en tiempo de compilación.

Uso del método de LINQ Cast insted:

table.Columns.Cast<DataColumn>() 

Eso es efectivamente un método de adaptador - cada elemento de la colección de columnas será echado perezosamente a DataColumn a medida que lo trae a partir del resultado.

La razón por la que compila foreach es que el compilador agrega un molde explícito para usted. Por ejemplo, esto va a compilar :

foreach (string x in table.Columns) 
{ 
} 

... pero va a lanzar una excepción en tiempo de ejecución.

+0

Gracias, eso es exactamente lo que necesitaba saber. –

3

Es porque DataColumnCollection implementa IEnumerable, pero no IEnumerable<T>.

var columns = (IEnumerable)(table.Columns) debería funcionar

IEnumerable y IEnumerable no están relacionados de ninguna manera. (Sin embargo IEnumerable<DataColumn> hereda de IEnumerable<object> cual podría pato de teclear para IEnumerable usando dinámica, pero que en realidad no le ayudan (incluso si es un montón de diversión))

+0

Creo que quería decir "[...] pero no IEnumerable [...]". – Tipx

0

Esto se debe a DataColumnCollection sólo se implementa IEnumerable, por lo que no puede emitir a la versión genérica IEnumerable<DataColumn>. Cuando se utiliza foreach, el compilador realiza la conversión por cada elemento por convención.

0

Prueba esto:

var columns = table.Columns as IEnumerable; 
1

En el primer caso se le carcasa individualmente cada vez dentro de la colección de columnas, pero en la segunda se está echando toda la colección a la vez.Es realmente no es diferente de:

// Cats implements IAnimal 
Cats[] cats = new Cats[20]; 
... 
IAnimal animal = cats[0]; 

frente

// this you cannot do 
Cats[] cats = new Cats[20]; 
IAnimal[] animal = cats; 

Sin embargo, es discutible, como se puede hacer esto:

table.Columns.Cast<DataColumn>() 

y hacerse con él. Tenga en cuenta que usar el Cast<> es preferible a simplemente obtener un IEnumerable genérico ya que se conserva la escritura fuerte.

Cuestiones relacionadas