【问题标题】:How to declare an array containing generic type?如何声明包含泛型类型的数组?
【发布时间】:2016-10-21 23:40:51
【问题描述】:

假设我有以下类型:

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

如何声明一个包含此类字段数组的变量?我尝试了以下方法:

var customFields = new Field[]
{
    new Field<string> { Name = "nickname", Value = "Bob" },
    new Field<int> { Name = "age", Value = 42 },
    new Field<DateTime> { Name = "customer_since", Value = new DateTime(2000, 12, 1) }
};

但我得到以下编译时异常:

使用泛型类型“字段”需要 1 个类型参数

我也尝试了var customFields = new Field&lt;object&gt;[],但出现以下错误:

无法将类型“Field”隐式转换为“Field”

无法将类型“Field”隐式转换为“Field”

无法将类型“Field”隐式转换为“Field”

【问题讨论】:

  • 每个泛型类型,都是一个不同的类型。因此,您正在尝试创建一组不同类型的实例。这是不可能的。这就像尝试创建一个将存储 stringint 值的数组。不过,你可以看看covariance

标签: c# generics


【解决方案1】:

正如 Matias 所说,不能那样做,因为 Field&lt;int&gt;Field&lt;string&gt; 是完全不同的类型。你可以做的是:

创建一个非通用的基础Field

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

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

然后:

var customFields = new Field[]
{
    new Field<string> { Name = "nickname", Value = "Bob" },
    new Field<int> { Name = "age", Value = 42 },
    new Field<DateTime> { Name = "customer_since", Value = new DateTime(2000, 12, 1) }
};

正如 Matias 所说,需要向下转换才能获得不同类型的 Value。如果对于每种不同类型的Value 都有特定的逻辑要执行,那么处理它的好方法是使用Factory 设计模式。工厂将为每个Field 返回一个正确的“FieldHandler&lt;T&gt;”,它将向下转换,执行操作并返回所需的内容。

【讨论】:

  • 仅供参考:您必须向下转换为泛型类型才能获得元素的 Value 属性。
  • 好主意!正如 Matias 所说,我必须强制转换才能获得价值,但在我的具体情况下,这没什么大不了的,因为我只支持字符串、int 和 DateTime。顺便说一句,有人知道我是否可以将 T 限制为仅这三种类型?类似于:where T: string, int, DateTime
  • 对于intDateTime,您可以使用struct 的通用约束,但对于字符串...
  • @desautelsj 我猜你能得到的最接近的是T : IComparable,但这也允许其他类型。基本上,任何可以比较的类型。
【解决方案2】:

您可以做的另一件事是简单地为所有这些类型使用公共基类 - 对象。

class Field
{
    public string Name { get; set; }
    public Object Value { get; set; }
}
var customFields = new Field[]
{
    new Field { Name = "nickname ", Value = "Bob" },
    new Field { Name = "age", Value = 42 },
    new Field { Name = "customer_since", Value = new DateTime(2000, 12, 1) }
};

但是,这会将一些类型处理卸载给 customFields 的使用者,但如果与特定字段名称关联的值类型已知,则应该没问题。

【讨论】:

  • 我同意你的第一种方法,这就是为什么它得到了我的支持,但版本却排在了底部——在这种情况下.. 为什么不使用泛型?.. :)
  • 你是对的!我的意思是添加白名单类型的情况,但即使使用泛型,您也可以限制使用 : Where T : [types allowed]。感谢您的支持:)
猜你喜欢
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
  • 2019-04-02
  • 1970-01-01
相关资源
最近更新 更多