2010-02-03 28 views
7

Un colega me señaló un caso extraño en C# (no estoy tan seguro de si esto realmente extraño).
Supongamos que tiene un empleado de la clase. Si desea crear una lista genérica <> de tipo Empleado, sólo tiene que hacer:
¿Por qué esto no es posible en C# Generics?

List<Employee> x = new List<Employee>; 

entiendo que tengo que pasar el tipo de empleado a la lista genérica para que conozca la información de tipo requerida acerca Empleado y genera métodos que devuelven y aceptan parámetros que son compatibles con Employee.

Ahora mi pregunta es, ¿por qué no es posible hacer lo siguiente?

Employee x = new Employee(); 
List<typeof(x)> list = new List<typeof(x)>(); 

Si esto no es suficiente la información requerida para la Lista <> saber, con el fin de crear una lista? En otras palabras, el tipo de x que es el tipo de empleado pasa ahora como un parámetro de tipo genérico a la lista <>, que (como yo solía creer) es lo mismo que pasar lista el nombre del tipo (en este caso, empleado) .

sé que algo como esto está disponible en Java (usando el .class) de palabras clave en una variable.

Estoy seguro de que me falta algo, así que, por favor, ¡enlight me guys!

Respuesta

30

No, el equivalente de ese no es disponible en Java. No puede usar "x.class" para obtener el tipo declarado de una variable.

Además, typeof(x) no funciona en C#, ya sea para obtener el tipo de una variable - que devuelve una referencia Type para el nombre tipo, por ejemplo typeof(string) devolverá una referencia al objeto Type asociado con el tipo System.String. Eso es equivalente a usar String.class en Java. (Tenga en cuenta que una vez más, eso se aplica a .class un nombre de tipo, no un nombre de variable.) Genéricos

Java no soportan nada como su declaración final tampoco. Si usted cree que lo hacen, por favor, dar una muestra :)

Lo que puede hacer en C# es el uso inferencia de tipos para hacer lo que desee:

public static List<T> CreateListForSampleType<T>(T sample) 
{ 
    return new List<T>(); 
} 

... 

Employee x = new Employee(); 
var list = CreateListForSampleType(x); 

Tenga en cuenta que no hay ninguna razón por la C# couldn 't se amplía para permitir algo como typeof(variablename) o List<typeof(variablename)> - después de todo, es información de tipo de tiempo de compilación. Sin embargo, no veo que cumpla con los requisitos de utilidad del equipo ... hay otras funciones mucho más útiles que me gustaría ver primero :)

+1

Buen ejemplo de código. ¿Qué pasaría si usa 'typeof' en la variable' list'? – FrustratedWithFormsDesigner

+1

typeof (list) daría lugar a un error de compilación. –

+0

Jon, gracias por tu respuesta detallada! Y como esta es información de tiempo de compilación, estoy en el camino correcto. Sin embargo, hablar de si es útil o no es un tanto controvertido;). – Galilyou

2

El motivo es que typeof() devuelve un Escriba object, mientras que necesita un nombre de tipo para inicializar una lista en tiempo de compilación.

1

typeof se usa con nombres de clase. Use GetType() en un objeto, pero solo en tiempo de ejecución ...

2

Una parte de la respuesta es que el tipo de x no está disponible en tiempo de compilación, es decirpodría ser creado usando algo como esto:

Employee x = EmployeeFactory.NewEmployee("John Doe"); // Returns TraineeEmployee, Employee or ManagementEmployee; 

List<typeof(x)> l = new List<typeof(x)> l(); // What type is it? 

Sin embargo, puede crear una lista de una clase base de lo que se desea almacenar en la lista (o incluso una lista de s "objeto").

1

Lo que hace falta - imho - es la diferencia entre una referencia de tipo estático en tiempo de compilación y una referencia de tipo dinamyc (a través de una instancia de System.Type) en tiempo de ejecución.

typeof() y .GetType() le dan el último. (para tipos e instancias, respectivamente)

Espero que lo aclare.

El código anterior de Jon Skeet es genial.

0

No se puede encontrar un motivo para crear una lista vacía desde C# 3.0.

generalmente puedo crear instancias de lista sólo con un método ToList de un IEnumerable, que a su vez genera utilizando un retorno rendimiento, Concat(), Repeat(), donde() etc.

var list = CreateEmployees().ToList(); 

,

public IEnumerable<Employee> CreateEmployees() 
{ 
yield return new Employee("Foo"); 
yield return new Employee("Bar"); 
}