C# - 一个列表中的多个泛型类型

Car*_*arl 140 c# generics

这可能是不可能的,但我有这个课程:

public class Metadata<DataType> where DataType : struct
{
    private DataType mDataType;
}
Run Code Online (Sandbox Code Playgroud)

还有更多,但让我们保持简单.泛型类型(DataType)仅限于where语句的值类型.我想要做的是拥有不同类型(DataType)的这些元数据对象的列表.如:

List<Metadata> metadataObjects;
metadataObjects.Add(new Metadata<int>());
metadataObjects.Add(new Metadata<bool>());
metadataObjects.Add(new Metadata<double>());
Run Code Online (Sandbox Code Playgroud)

这甚至可能吗?

lep*_*pie 179

public abstract class Metadata
{
}

// extend abstract Metadata class
public class Metadata<DataType> : Metadata where DataType : struct
{
    private DataType mDataType;
}
Run Code Online (Sandbox Code Playgroud)

  • 与简单的`List <object>`相比,这种方法有什么好处?请查看我在OP的问题下发表的评论. (9认同)
  • @SaebAmini List <object>没有向开发人员显示任何意图,也没有阻止开发人员错误地将一些非MetaData对象添加到列表中.通过使用List <MetaData>,可以理解列表应包含的内容.最有可能的MetaData将具有一些未在上面的示例中显示的公共属性/方法.通过对象访问这些将需要繁琐的演员. (7认同)
  • 哇!我真的不认为那是可能的!你是一个救生员,伙计! (5认同)
  • 这个+10!我不知道为什么这会编译..正是我需要的! (2认同)
  • - 回答问题的正确答案 - 拒绝进一步详细说明 - 离开 * 插入 giga chad meme * (2认同)

bru*_*nde 90

根据leppie的回答,为什么不建立MetaData一个界面:

public interface IMetaData { }

public class Metadata<DataType> : IMetaData where DataType : struct
{
    private DataType mDataType;
}
Run Code Online (Sandbox Code Playgroud)

  • 因为没有共享的共同功能 - 为什么要浪费一个基类呢?界面就足够了 (32认同)
  • 因为您可以在struct中实现接口. (2认同)
  • 然而,使用虚方法的类继承大约比接口方法快 1.4 倍。因此,如果您计划在 MetaData&lt;DataType&gt; 中实现任何非通用 MetaData(虚拟)方法/属性,如果性能是一个问题,请选择抽象类而不是接口。否则,使用接口可以更灵活。 (2认同)

Bry*_*tts 29

我还使用了非通用版本,使用new关键字:

public interface IMetadata
{
    Type DataType { get; }

    object Data { get; }
}

public interface IMetadata<TData> : IMetadata
{
    new TData Data { get; }
}
Run Code Online (Sandbox Code Playgroud)

显式接口实现用于允许两个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; }
}
Run Code Online (Sandbox Code Playgroud)

您可以派生一个版本定位值类型:

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)
    {}
}
Run Code Online (Sandbox Code Playgroud)

这可以扩展到任何类型的通用约束.

  • +1只是因为你正在展示如何使用它(`DataType`和`object Data`帮了很多) (4认同)
  • 我似乎无法编写例如`Deserialize <metadata.DataType>(metadata.Data);`.它告诉我*无法解析符号元数据*.如何检索DataType以将其用于通用方法? (4认同)