代码之家  ›  专栏  ›  技术社区  ›  this. __curious_geek

如果T类型需要实例化,为什么泛型类签名需要指定new()?

  •  13
  • this. __curious_geek  · 技术社区  · 15 年前

    我正在编写一个泛型类,如下所示。

    public class Foo<T> : 
        where T : Bar, new()
    {
        public void MethodInFoo()
        {
            T _t = new T();
        }
    }
    

    就像你看到的那样 _t 类型为t的在运行时实例化。为了支持泛型类型t的实例化,该语言强制我在类签名中放置new()。如果bar是一个抽象类,我同意这一点,但是如果bar标准的非抽象类带有公共的无参数构造函数,为什么需要这样做呢?

    如果未找到new(),编译器将提示以下消息。

    无法创建变量类型“t”的实例,因为它没有new()约束

    7 回复  |  直到 8 年前
        1
  •  22
  •   Peter Badida I'm Geeker    8 年前

    因为通常没有假设模板参数需要[非抽象和]可构造[通过公共无参数构造函数]才能使类型与模板参数定义匹配。

    直到你添加一个 :new() 对模板的约束:

    • 编译器不允许您构造 T
    • 编译器会让你匹配 T 具有抽象类型或没有公共无参数构造函数的类型

    这个 :Bar 位是正交的,表示:

    • 不要让人们与非派生自[或是]的类型匹配 Bar
    • 让我铸造 T S至 酒吧 或派生自 酒吧 体内
    • 让我调用public和in-scope内部方法 酒吧 在一 T
        2
  •  11
  •   AakashM    15 年前

    只是因为 Bar 类定义了一个无参数的构造函数,但并不意味着 酒吧 将执行此操作-可能有一个类继承自 酒吧 但隐藏了无参数构造函数。这样的班级会遇到 酒吧 约束但正确地失败了 new() 约束。

    (注意,如果你 酒吧 sealed 为了避免这种可能性,您可以(可以理解)不再将其用作一般约束- 编辑 尝试此操作会产生编译器错误CS0701。

        3
  •  3
  •   LukeH    15 年前

    可能是因为如果你不包括 new() 约束然后 T 可以合法地是 Bar 没有默认(即,public和无参数)构造函数,在这种情况下, new T() 方法内的语句无效。

    1. 仅用 酒吧 作为约束条件, T 可以是 酒吧 或任何衍生的 酒吧 ,有或没有默认构造函数。
    2. 仅用 新() 作为约束条件, T 可以是具有默认构造函数的任何类型。
    3. 酒吧 新() 作为约束条件, T 必须是 酒吧 酒吧 并且还必须有一个默认的构造函数。
        4
  •  2
  •   Sean Reilly    15 年前

    因为bar的子类可能没有no arg构造函数。

    where T : Bar
    

    指示条或条的子类。如果你只是想要一个Bar的实例,你就不会使用泛型。在很多实例中(例如,对象和字符串),超类有一个无参数的构造函数,而子类没有。

        5
  •  1
  •   GraemeF    15 年前

    虽然 Bar 可能是具体的,派生类 T 本身可能是抽象的或缺少默认构造函数。

        6
  •  1
  •   mbillard    15 年前

    您可能已经使用了bar构造函数:

    T _t = new Bar();
    

    没有 new() 约束。但是,您使用 T 构造函数和编译器不能也不假定构造绑定到t的类型是可能的,除非添加新的()约束。

        7
  •  0
  •   Ruben Bartelink    15 年前

    对于不确定的人,请记住您可以使用

    where T : IDeviceCommand
    

    要求T实现一些接口作为最低合同要求。您可以将上面的描述为“如果提供的类型至少为“T”,则可以调用我,实现IDeviceCommand接口”。当然,这允许您对“T”提供的操作方法进行一系列(正确的)假设。