【问题标题】:Cannot create an instance of the variable type 'Item' because it does not have the new() constraint无法创建变量类型“Item”的实例,因为它没有 new() 约束
【发布时间】:2013-02-04 22:27:20
【问题描述】:

我正在尝试测试一种方法 - 并收到错误:

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

以下所需信息:

public interface IHasRect
{
    Rectangle Rectangle { get; }
}

助手类:

class Item : IHasRect
{
    public Item(Point p, int size)
    {
        m_size = size;
        m_rectangle = new Rectangle(p.X, p.Y, m_size, m_size); 
    }
}

对于要测试的函数,我需要实例化一个对象...

public class SomeClass<T> where T : IHasRect

测试:

public void CountTestHelper<Item>() where Item : IHasRect
{
    Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
    SomeClass<Item> target = new SomeClass<Item>(rectangle);            
    Point p = new Point(10,10);
    Item i = new Item(p, 10);      // error here        
    ...
}
[TestMethod()]
public void CountTest()
{
    CountTestHelper<Item>();
}   

我试图通过阅读 http://msdn.microsoft.com/en-us/library/d5x73970.aspxhttp://msdn.microsoft.com/en-us/library/x3y47hd4.aspx 来了解此错误的含义或解决方法 - 但它没有帮助。

我不明白这个错误 - 我已经将“SomeClass”限制为类型。我无法约束整个 Test 类(由 Visual Studio 生成的单元测试类,其中包含所有测试) - 否则我会得到许多其他错误。 Item 类没有任何模板...

【问题讨论】:

    标签: c# templates generics compiler-errors


    【解决方案1】:

    除非您使用new 关键字将其标记为实现默认构造函数,否则您无法初始化泛型类型对象:

    public void CountTestHelper<Item>() where Item : IHasRect, new()
     {
        Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
        SomeClass<Item> target = new SomeClass<Item>(rectangle);            
        Point p = new Point(10,10);
        Item i = new Item();    // constructor has to be parameterless!
        ...
     }
    

    另一方面,如果您尝试初始化在应用程序其他位置定义的 Item 类型对象,请尝试使用它之前的命名空间:

    MyAppNamespace.Item i = new MyAppNamespace.Item(p, 10);
    

    【讨论】:

    • 除了只能用new()的无参构造函数。我不明白他们为什么没有解决这个问题!编辑:啊,你已经编辑提到了;)
    • 'Item' 必须是具有公共无参数构造函数的非抽象类型,才能将其用作泛型类型或方法 'CountTestHelper()' 中的参数 'Item'
    • 另外,请注意 Lee 的回答,确保您熟悉泛型类型定义。在这里,您的“Item”类不是您之前定义的类,它只是您临时调用 Item 的占位符类型...
    • 是否有允许 new(parameter1, parameter2, etc) 用于泛型 T 类型的版本?
    【解决方案2】:

    因为很多人是通过问题tilte(非常通用并且与编译器消息匹配)到达这里的,所以让我对编译错误itef给出更详细的答案。

    您在方法中使用泛型。编译器不知道它将接收哪种类型,因此不保证您的类型具有无参数构造函数。例如:

    class A {
        A(int i){ ... }
    }
    
    class B { ... }
    
    public void MyMethod<T>(){
        T t = new T(); //This would be fine if you use 'MyMethod<B>' but you would have a problem calling 'MyMethod<A>' (because A doesn´t have a parameterless construtor;
    }
    

    要解决这个问题,您可以告诉编译器您的泛型参数有一个无参数构造函数。这是通过定义约束来完成的:

    public void MyMethod<T>()  where T: new(){
        T t = new T(); //Now it's ok because compiler will ensure that you only call generic method using a type with parameterless construtor;
    }
    

    更多关于构造函数约束的信息可以在这里找到: https://msdn.microsoft.com/en-us/library/bb384067.aspx

    【讨论】:

    • Public Sub MyMethod(Of T As New)() 是等效的 VB 代码,供感兴趣的人使用。更多信息请访问MSDN
    【解决方案3】:

    该行中的Item

    Item i = new Item(p, 10);
    

    指的是CountTestHelper方法的泛型类型参数Item,而不是类Item。更改通用参数名称,例如

    public void CountTestHelper<TItem>() where TItem : IHasRect
    {
        Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
        SomeClass<TItem> target = new SomeClass<TItem>(rectangle);            
        Point p = new Point(10,10);
        Item i = new Item(p, 10);    
        ...
    }
    

    或者,您可以完全限定要创建的 Item 类的名称:

    public void CountTestHelper<Item>() where Item : IHasRect
    {
        Rectangle rectangle = new Rectangle(0, 0, 100, 100); 
        SomeClass<Item> target = new SomeClass<Item>(rectangle);            
        Point p = new Point(10,10);
        SomeNamespace.Item i = new SomeNamespace.Item(p, 10);  
    }
    

    【讨论】:

    • 你看到的和我一样。我看着它,就像“等等,Item是一个类型参数而不是一个类型。
    • 这个答案对这个问题是正确的。但是,如果您来这里是为了寻找一种方法来实例化具有泛型类型的属性,您将需要阅读@MarcinJuraszek 的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多