Невозможно создать экземпляр типа переменной "Item", потому что у него нет ограничения new()
Я пытаюсь проверить метод - и получаю сообщение об ошибке:
Невозможно создать экземпляр типа переменной "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.aspx и http://msdn.microsoft.com/en-us/library/x3y47hd4.aspx, но это не помогает.
Я не понимаю эту ошибку - я уже ограничил тип SomeClass. Я не могу ограничить весь класс Test (класс модульных тестов, сгенерированный Visual Studio, который содержит все тесты) - в противном случае я получу ряд других ошибок. Класс Item не имеет шаблона...
Ответы
Ответ 1
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);
}
Ответ 2
Вы не можете инициализировать объект Generic type, если вы не помечаете его как реализующий конструктор по умолчанию, используя ключевое слово 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);
Ответ 3
Поскольку многие люди попадают сюда на вопрос tilte (который очень общий и соответствует сообщению компилятора), позвольте мне дать более подробный ответ об ошибке компиляции itsef.
В методе используются дженерики. Компилятор не знает, какой тип он получит, и, следовательно, не является гарантией того, что ваш тип имеет бесступенчатый конструктор. Для примера:
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 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