Общий метод добавить новый 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 parameterT'в универсальном типе или методе

Что я пытаюсь сделать возможным? Я чувствую, что так должно быть, так как компилятору не важно, какой это список - ему просто нужно вызвать открытый конструктор без параметров и добавить новый экземпляр в существующий список, который был передан.

Я догадывался, что проблема в том, что интерфейс не гарантирует, что его разработчики будут иметь открытый конструктор, но даже если я дам ему конкретный класс, я получу эту ошибку:

Тип T' must be convertible toBayClass'для использования его в качестве параметра `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(),

Другие вопросы по тегам