2011-08-24 11 views
64

Suponga que tiene una clase básica Employee como tal:La conversión a IEnumerable <T>

class Employee 
{ 
    public string Name; 
    public int Years; 
    public string Department; 
} 

Entonces (en una clase separada) que tienen los siguientes fragmentos de código (creo que entiendo todos excepto el último):

Creo que el siguiente fragmento de código funciona porque el iniciador de la matriz crea una matriz de objetos Employee que son del mismo tipo que la variable de la fuerza de trabajo a la que se está asignando.

Employee[] workforceOne = new Employee[] { 
    new Employee() { Name = "David", Years = 0, Department = "software" }, 
    new Employee() { Name = "Dexter", Years = 3, Department = "software" }, 
    new Employee() { Name = "Paul", Years = 4, Department = "software" } }; 

Tengo el siguiente fragmento de código. Creo que esto funciona porque la matriz de Employee objetos implicity es una implementación de la clase Array() que implementa IEnumerable. Por lo tanto, creo que esta es la razón por la matriz se puede asignar a IEnumerable?

IEnumerable workforceTwo = new Employee[] { 
    new Employee() { Name = "David", Years = 0, Department = "software" }, 
    new Employee() { Name = "Dexter", Years = 3, Department = "software" }, 
    new Employee() { Name = "Paul", Years = 4, Department = "software" } }; 

entonces tengo este fragmento de código:

IEnumerable<Employee> workforceThree = new Employee[] { 
    new Employee() { Name = "David", Years = 0, Department = "software" }, 
    new Employee() { Name = "Dexter", Years = 3, Department = "software" }, 
    new Employee() { Name = "Paul", Years = 4, Department = "software" } }; 

No estoy seguro de por qué este fragmento de código funciona?IEnumerable<Employee> hereda de IEnumerable (? Y sustituciones (o sobrecargas) el método GetEnumerator()) pero no deben i por lo tanto, es necesaria una conversión de lo anterior para trabajar como tal:

//The cast does work but is not required 
IEnumerable<Employee> workforceFour = (IEnumerable<Employee>)new Employee[] { 
    new Employee() { Name = "David", Years = 0, Department = "software" }, 
    new Employee() { Name = "Dexter", Years = 3, Department = "software" }, 
    new Employee() { Name = "Paul", Years = 4, Department = "software" } }; 

Parece que la matriz está siendo implícitamente abajo emitir desde un tipo de IEnumerable a IEnumerable<Employee>, pero siempre pensé que cuando necesitabas convertir un tipo a algo más específico necesitabas un lanzamiento explícito.

Tal vez me está perdiendo algo simple en mi comprensión aquí, pero alguien puede por favor ayudarme con mi comprensión al respecto.

Gracias.

+0

¿Cuál es la pregunta aquí? – Aliostad

+3

@Aliostad: está justo debajo del fragmento 'workforceThree'. – Heinzi

+3

+1 ¡Gran pregunta! – Gishu

Respuesta

93

De the documentation:

En la versión 2.0 de .NET Framework, la clase Array implementa los System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T> y System.Collections.Generic.IEnumerable<T> interfaces genéricas. Las implementaciones se proporcionan a las matrices en tiempo de ejecución y, por lo tanto, no son visibles para las herramientas de creación de documentación. Como resultado, las interfaces genéricas no aparecen en la sintaxis de declaración para la clase Array, y no hay temas de referencia para los miembros de la interfaz a los que solo se puede acceder lanzando una matriz al tipo de interfaz genérica (implementaciones de interfaz explícita).

Por lo tanto, sus implementos Employee[]IEnumerable<Employee>.

+3

Para aclarar, no es la clase Array que lo implementa, es T [] de cualquier T. – IllidanS4

4

se necesita el conjunto de la plantilla por defecto implementos IEnumerable<Employee> así como IEnumerable

3

conversión explícita cuando alguna frase tiene que ser downcasted. Eso está lanzando un objeto a un tipo más especializado, si el objeto es de tipo especializado.

Por otro lado, upcasting (conversión a un tipo menos especializado), nunca necesitará un lanzamiento explícito, pero puede hacerlo explícitamente (es inútil).

Desde matriz implementa IEnumerable y IEnumerable<T>, estás haciendo una conversión hacia arriba en su código, lo que significa _Usted no es necesario para convertir explícitamente a IEnumerable<T>.

+3

No estoy de acuerdo. En algún caso, necesitas un upcast explícito. Como un ejemplo función de anulación: DoStuffs void (IEnumerable objetos) {...} DoStuffs void (params T [] objetos) {((IEnumerable ) objetos) DoStuffs; } – Orace

+2

@Orace Esto no es exactamente un upcast ... Es una ayuda del compilador para que invoque la sobrecarga deseada ... ¿estás de acuerdo? ;) Es un problema de resolución de sobrecarga de método. –

+0

@Orace Bueno, es un upcast, pero quiero decir que necesitas el "molde" explícito para invocar la sobrecarga deseada ... –

Cuestiones relacionadas