Общий метод добавить новый T в список T
Я пытаюсь передать общий список в функцию, которая добавит новый элемент в список. У меня есть следующий урезанный пример:
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 parameter
T'в универсальном типе или методе
Что я пытаюсь сделать возможным? Я чувствую, что так должно быть, так как компилятору не важно, какой это список - ему просто нужно вызвать открытый конструктор без параметров и добавить новый экземпляр в существующий список, который был передан.
Я догадывался, что проблема в том, что интерфейс не гарантирует, что его разработчики будут иметь открытый конструктор, но даже если я дам ему конкретный класс, я получу эту ошибку:
Тип
T' must be convertible to
BayClass'для использования его в качестве параметра `T' в универсальном типе или методе
Был бы очень благодарен за любые указатели.
2 ответа
Я думаю, что ваш код вызова выглядит
void Method<T>(ObservedList<T> bayList)
{
SetBayNumb<T>(bayList);
}
Проблема возникает из-за того, что нет никаких ограничений на T
в Method
и, следовательно, компилятор не может сопоставить аргументы для SetBayNumb
,
Обратите внимание, что имя общего типа это просто имя - вы можете выбрать любое имя, которое вам нравится, и это может помочь при рассуждении об ошибке. Переписать один и тот же метод с универсальным аргументом с другим именем, например:
void Method<TArg>(ObservedList<TArg> bayList)
{
SetBayNumb<TArg>(bayList);
}
дает лучшую ошибку:
Тип 'TArg' должен иметь открытый конструктор без параметров, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе.
Обратите внимание, что в этой ошибке есть 2 разных типа (которые трудно увидеть, когда оба называются одной и той же буквой "T").
Исправления:
- указать те же ограничения на внешний универсальный метод (
Method<TArg>(ObservedList<TArg> bayList) where TArg : ... new()
) - уточнить
T
на уровне общего класса вместо отдельного метода - передать конкретный класс, который удовлетворяет обоим требованиям (класс для элементов в списке должен реализовывать интерфейс и иметь конструктор без параметров).
Жалоба не о списке, а о T
, Если у вас есть ObservedList<MyClass>
и передать его SetBayNumb()
, MyClass
должен реализовать IBaySpec
и он должен иметь конструктор без параметров: public MyClass() { ... }
, Зачем? Потому что вот что where T : IBaySpec, new()
говорит. Если вы удалите where
оговорка, ошибка исчезнет, но вы больше не сможете сказать new T()
,