【问题标题】:C# - Multiple generic types in one listC# - 一个列表中的多个泛型类型
【发布时间】:2008-12-09 15:29:58
【问题描述】:

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

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

还有更多内容,但让我们保持简单。泛型类型(DataType)被 where 语句限制为值类型。我想要做的是列出这些不同类型的元数据对象(DataType)。如:

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

这可能吗?

【问题讨论】:

  • 我想知道与仅使用 List&lt;object&gt; 相比,以下答案中的方法是否有任何真正的好处?他们不会停止装箱/拆箱,他们不会消除铸造的需要,最终,你会得到一个 Metadata 对象,它不会告诉你任何关于实际 DataType 的信息,我正在寻找解决方案解决这些问题。如果您要声明一个接口/类,只是为了能够将实现/派生的泛型类型放在泛型列表中,这与使用 List&lt;object&gt; 相比 多么不同除了没有意义的层?
  • 抽象基类和接口都通过限制可以添加到列表中的元素类型来提供一定程度的控制。我也看不出拳击是如何进入这个领域的。
  • 当然,如果您使用的是 .NET v4.0 或更高版本,那么协方差就是解决方案。 List&lt;Metadata&lt;object&gt;&gt; 成功了。
  • @0b101010 我也是这么想的,但不幸的是,值类型上不允许有差异。由于 OP 有一个 struct 约束,它在这里不起作用。 See
  • @0b101010,两者都只限制引用类型,任何内置值类型和任何结构仍然可以添加。此外,最后,您有一个 MetaData 引用类型列表,而不是您的原始值类型,没有关于每个元素的基础值类型的(编译时)信息,这 实际上是“装箱” .

标签: c# generics


【解决方案1】:
public abstract class Metadata
{
}

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

【讨论】:

  • 哇!我真的没想到这是可能的!你是一个救生员,伙计!
  • 为此+10!我不知道为什么会这样编译.. 正是我需要的!
  • 我也有类似的问题,但是我的泛型类是从另一个泛型类扩展而来的,所以我不能使用您的解决方案...关于解决这种情况的任何想法?
  • 与简单的List&lt;object&gt; 相比,这种方法有什么好处吗?请查看我在 OP 问题下发表的评论。
  • @SaebAmini A List 不会向开发人员显示任何意图,也不会阻止开发人员通过错误地将一些非 MetaData 对象添加到列表中而自取其辱。通过使用 List 可以了解列表应包含的内容。很可能 MetaData 将具有一些在上述示例中未显示的公共属性/方法。通过对象访问它们需要繁琐的转换。
【解决方案2】:

按照leppie的回答,为什么不把MetaData做成一个接口:

public interface IMetaData { }

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

【讨论】:

  • 谁能告诉我为什么这种方法更好?
  • 因为没有共享通用功能——那为什么要在上面浪费一个基类呢?一个接口就足够了
  • 因为可以在struct中实现接口。
  • 然而,使用虚拟方法的类继承比接口方法快大约 1.4 倍。因此,如果您计划在 MetaData 中实现任何非泛型 MetaData(虚拟)方法/属性,如果考虑性能,请选择抽象类而不是接口。否则,使用接口会更灵活。
【解决方案3】:

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

public interface IMetadata
{
    Type DataType { get; }

    object Data { get; }
}

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

显式接口实现用于同时允许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; }
}

您可以派生一个针对值类型的版本:

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)
    {}
}

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

【讨论】:

  • +1 只是因为您正在展示如何使用它(DataTypeobject Data 帮助很大)
  • 我好像不会写,例如Deserialize&lt;metadata.DataType&gt;(metadata.Data);。它告诉我无法解析符号元数据。如何检索 DataType 以将其用于泛型方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 2021-10-31
  • 2011-12-25
相关资源
最近更新 更多