2010-04-23 26 views
10

Estoy tratando de almacenar una lista de objetos genéricos en una lista genérica, pero estoy teniendo dificultades para declararla. Mi objeto se parece a:Una lista genérica de genéricos

public class Field<T> 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public T Value { get; set; } 

    /* 
    ... 
    */ 
} 

Me gustaría crear una lista de estos. Mi problema es que cada objeto en la lista puede tener un tipo separado, por lo que la lista poblada podría contener algo como esto:

{ Field<DateTime>, Field<int>, Field<double>, Field<DateTime> } 

Entonces, ¿cómo os anuncio que?

List<Field<?>> 

(me gustaría quedarse como typesafe como sea posible, así que no quiero usar un ArrayList).

+0

Es una idea interesante "mantenerse lo más seguro posible", sin embargo, ¿no está violando el concepto http://en.wikipedia.org/wiki/YAGNI? Piensa cómo vas a acceder a esa lista, ¿realmente la necesitas de manera tan específica? –

Respuesta

21

Esta es la situación en la que puede beneficio que tener una clase abstracta de base (o interfaz) que contiene los bits no genéricas:

public abstract class Field 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

public class Field<T> : Field 
{  
    public T Value { get; set; } 

    /* 
    ... 
    */ 
} 

, entonces puede tener un List<Field>. Eso expresa toda la información que realmente sabes sobre la lista. No conoce los tipos de valores de los campos, ya que pueden variar de un campo a otro.

+0

@Jon - ¿La primera clase debería ser genérica o simplemente una clase simple? – Giorgi

+1

@Giorgi, 'clase abstracta Campo ' parece un error tipográfico. Me he tomado la libertad de corregirlo. –

+0

Aún tiene que transmitir para obtener el tipo de valor real ... pero esta es la única solución que puedo pensar también, sin un tipo de "tupla" real. – tames

5

Quizás implemente una interfaz.

interface IField 
{ 
} 

class Field<T> : IField 
{ 
} 

...

List<IField> fields = new List<IField>() { new Field<int>(), new Field<double>() }; 
+0

Esto lo deja en la misma posición porque IField no contendrá el tipo (T). No mucho diferente de simplemente usar 'object' porque todavía tendrá que lanzar para obtener el valor. – tames

+0

@tames, está en una mejor posición porque los elementos de su lista deben implementar IField (o heredar de Field, en el ejemplo de Jon). la lista todavía se escribe con más fuerza que una lista de objetos. –

+0

@anthony ...Estoy de acuerdo, y he usado soluciones de interfaz y de clase base. – tames

5

No se puede declarar una lista de tipos genéricos sin conocer el tipo genérico en tiempo de compilación.

Se puede declarar un List<Field<int>> o una List<Field<double>>, pero no hay otro tipo de base común para Field<int> y Field<double> que object. Entonces, el único List<T> que podría contener diferentes tipos de campos sería List<object>.

Si desea un tipo más específico para la lista, debe hacer que la clase Field<T> herede una clase o implemente una interfaz. Entonces puede usar eso para el tipo genérico en la lista.

Cuestiones relacionadas