【问题标题】:Generic method add new T to list of T通用方法将新 T 添加到 T 列表
【发布时间】:2015-02-05 22:00:14
【问题描述】:

我正在尝试将通用列表传递给将向列表添加新项目的函数。我有以下精简示例:

   private void SetBayNumb<T>(ObservedList<T> bayList) where T : IBaySpec, new()
   {
     var bay = new T();
     bayList.Add(bay);
   }

调用它的方法有这个错误:

泛型类型或方法中的类型T' must have a public parameterless constructor in order to use it as parameterT'

我正在尝试做的事情可能吗?我觉得它一定是因为编译器不应该关心它是什么类型的列表 - 它只需要调用公共的无参数构造函数并将新实例添加到传入的现有列表中。

我猜问题是接口不保证它的实现者会有一个公共构造函数,但是即使我给它一个具体的类我也会得到这个错误:

类型T' must be convertible toBayClass' 为了使用它 作为泛型类型或方法中的参数“T”

非常感谢任何指点。

【问题讨论】:

  • 您收到错误是因为您指定的类型不满足通用约束。
  • 显示调用它的方法——它显然使用了T 的类型,它没有公共的无参数构造函数(请记住,构造函数不是继承的)
  • 阅读错误信息,它会告诉你到底出了什么问题..
  • @MethodMan 实际上我认为它不是因为涉及 2 个同名类型,而且很难区分它们......(我添加了显示错误的答案)。

标签: c# generics generic-constraints


【解决方案1】:

投诉不是关于列表,而是关于T。如果你有一个ObservedList&lt;MyClass&gt; 并将它传递给SetBayNumb()MyClass 必须实现IBaySpec 并且它必须有一个无参数的构造函数:public MyClass() { ... }。为什么?因为这就是where T : IBaySpec, new() 所说的。如果您删除where 子句,错误将消失,但您将无法再说出new T()

【讨论】:

  • 很好的解释,但我认为这是答案的一半 - 错误消息中有两个“T”,它们是不同的(我的答案试图显示问题的后半部分)。跨度>
  • @AlexeiLevenkov:好点;我对此表示赞同。
【解决方案2】:

我认为你的调用代码看起来像

 void Method<T>(ObservedList<T> bayList)
 {
    SetBayNumb<T>(bayList);
 }

问题在于TMethod 中没有限制,因此编译器无法匹配SetBayNumb 的参数。

请注意,泛型类型名称只是名称 - 您可以选择任何您喜欢的名称,它可以帮助推理错误。用不同命名的泛型参数重写相同的方法,例如:

 void Method<TArg>(ObservedList<TArg> bayList)
 {
    SetBayNumb<TArg>(bayList);
 }

给出更好的错误:

类型“TArg”必须具有公共无参数构造函数,才能在泛型类型或方法中将其用作参数“T”

请注意,错误涉及两种不同的类型(当两者都称为相同的“T”时很难看出)。

修复:

  • 对外部泛型方法指定相同的限制 (Method&lt;TArg&gt;(ObservedList&lt;TArg&gt; bayList) where TArg : ... new())
  • 在泛型类级别而不是单个方法上指定 T
  • 传递满足这两个要求的具体类(列表中项目的类应实现接口并具有无参数构造函数)。

【讨论】:

  • 重命名 T 的好技巧,这样错误就变得清晰了。我的调用函数如你所说,但有 Ibay 约束......但没有 new()。添加修复它。
  • 让我检查一下我明白为什么 - 是因为编译器现在可以安全地说 TArg 传递给 SetBayNumb 函数,满足 new() 约束吗?否则它不会知道它所传递的类型是否有正确的构造函数。
  • @DBHC - 是的。如果 TArg 的约束少于 T ,则您可以将更多类型作为 TArgs 传递,其中许多类型将不满足 T 的约束 - 所以编译器确实需要停止这种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多