2008-12-09 11 views
105

Esto probablemente no es posible, pero tengo esta clase:C# - tipos genéricos múltiples en una sola lista

public class Metadata<DataType> where DataType : struct 
{ 
    private DataType mDataType; 
} 

No hay más que eso, pero vamos a mantenerlo simple. El tipo genérico (DataType) está limitado a los tipos de valor por la instrucción where. Lo que quiero hacer es tener una lista de estos objetos de metadatos de diferentes tipos (DataType). Tales como:

List<Metadata> metadataObjects; 
metadataObjects.Add(new Metadata<int>()); 
metadataObjects.Add(new Metadata<bool>()); 
metadataObjects.Add(new Metadata<double>()); 

¿Esto es posible?

+21

Me pregunto si hay algún beneficio real para los enfoques en las respuestas a continuación en comparación con el uso de una 'Lista '? No detendrán el boxeo/unboxing, no eliminarán la necesidad de lanzar, y en última instancia, obtendrás un objeto 'Metadata' que no te dice nada sobre el' DataType' real, yo estaba buscando una solución para abordar esos problemas. Si va a declarar una interfaz/clase, solo por el hecho de poder poner el tipo genérico de implementación/derivado en una lista genérica, simplemente _how different_ es eso que usar 'List ' que no sea tener una capa sin sentido ? –

+8

Tanto la clase base abstracta como la interfaz proporcionan un grado de control al restringir el tipo de elementos que se pueden agregar a la lista. Tampoco puedo ver cómo el boxeo entra en esto. – 0b101010

+1

Por supuesto, si usa .NET v4.0 o superior, entonces la covarianza es la solución. 'List >' hace el truco. – 0b101010

Respuesta

139
public abstract class Metadata 
{ 
} 

// extend abstract Metadata class 
public class Metadata<DataType> : Metadata where DataType : struct 
{ 
    private DataType mDataType; 
} 
+4

¡Guau! ¡Realmente no pensé que eso fuera posible! Eres un salvavidas, hombre! – Carl

+2

+10 para esto! No sé por qué esto compila ... ¡Exactamente lo que necesitaba! – Odys

+0

Tengo un problema similar, pero mi clase genérica se extiende desde otra clase genérica, por lo que no puedo usar su solución ... ¿Alguna idea sobre una solución para esta situación? – Sheridan

69

Tras la respuesta de leppie, por qué no hacer MetaData una interfaz:

public interface IMetaData { } 

public class Metadata<DataType> : IMetaData where DataType : struct 
{ 
    private DataType mDataType; 
} 
+0

¿Puede alguien decirme por qué este enfoque es mejor? – Lazlo

+24

Porque no se comparte ninguna funcionalidad común, ¿por qué perder una base? clase en eso entonces? Una interfaz es suficiente – flq

+2

Porque puede implementar interfaces en la estructura –

25

También he utilizado una versión no genérica, utilizando el new palabra clave:

public interface IMetadata 
{ 
    Type DataType { get; } 

    object Data { get; } 
} 

public interface IMetadata<TData> : IMetadata 
{ 
    new TData Data { get; } 
} 

aplicación explícita de interfaces se usa para permitir ambos miembros Data:

public class Metadata<TData> : IMetadata<TData> 
{ 
    public Metadata(TData data) 
    { 
     Data = data; 
    } 

    public Type DataType 
    { 
     get { return typeof(TData); } 
    } 

    object IMetadata.Data 
    { 
     get { return Data; } 
    } 

    public TData Data { get; private set; } 
} 

Usted podría derivar una versión focalización tipos de valores:

public interface IValueTypeMetadata : IMetadata 
{ 

} 

public interface IValueTypeMetadata<TData> : IMetadata<TData>, IValueTypeMetadata where TData : struct 
{ 

} 

public class ValueTypeMetadata<TData> : Metadata<TData>, IValueTypeMetadata<TData> where TData : struct 
{ 
    public ValueTypeMetadata(TData data) : base(data) 
    {} 
} 

Esto se puede extender a cualquier tipo de limitaciones genéricas.

+4

+1 solo porque está mostrando cómo usarlo ('DataType' y' Objeto Data' ayudó mucho) – Odys

+4

No parece que pueda escribir, por ejemplo, 'Deserialize < metadata.DataType> (metadata.Data); '. Me dice * no puede resolver los metadatos del símbolo *. ¿Cómo recuperar el DataType para usarlo en un método genérico? –