web-dev-qa-db-ja.com

new()制約がないため、変数タイプ 'Item'のインスタンスを作成できません

メソッドをテストしようとしています-エラーが発生しています:

Cannot create an instance of the variable type 'Item' because it does not have the new() constraint

以下に必要な情報:

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.aspx および httpを読んで、このエラーの意味、または修正方法を理解しようとしています。 ://msdn.Microsoft.com/en-us/library/x3y47hd4.aspx -しかし、それは役に立ちません。

私はこのエラーを理解していません-「SomeClass」を既に型に制限しています。 Testクラス全体(Visual Studioで生成され、すべてのテストを含むユニットテストクラス)全体を制約することはできません-そうでなければ、他の多くのエラーが発生します。 Itemクラスにはテンプレートがありません...

このエラーの修正を手伝ってください。ありがとうございました。

38
Thalia

行のItem

Item i = new Item(p, 10);

クラスItemではなく、CountTestHelperメソッドのジェネリック型パラメーター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);  
}
12
Lee

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);
109
MarcinJuraszek

ティルト(非常に一般的であり、コンパイラメッセージに一致する)で多くの人がここに来るので、コンパイルエラー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

28
Zé Carlos