c # Generics: Передача List <string>методу, который ожидает List <T> - PullRequest
5 голосов
/ 09 мая 2011

У меня был первый набег на дженерики, и я их немного понимаю.У меня есть метод, предназначенный для приема двух списков любого объекта, сопоставления их различными способами и возврата совпадающих / несопоставленных объектов (вещи внутри метода, вероятно, здесь не являются ключевыми).Цель состоит в том, чтобы принять любой тип объекта, будь то клиенты или что-то еще.Тем не менее, я столкнулся с трудностью, заставляя его принимать 'string', я полагаю, потому что он не инициализирован с ключевым словом new () и не похож на обычный экземплярный класс.

Итак, яиметь объявление метода, например, так:

public static compareResult<T> stepCompare<T>(List<T> leftList, List<T> rightList, Comparison<T> IDComparer = null, Comparison<T> lowLevelComparer = null, bool confirmUniqueness = true) where T : IComparable, new()

По общему признанию, добавление предложения where в конце было в ответ на ошибку "не может создать экземпляр типа переменной" T ", потому что у него нет нового() ограничение ".Это появилось против строки в методе, говорящей

T lastItem = new T();

Однако, теперь, если я пытаюсь передать два Lists<string>, он говорит: "'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'MF.Comparers.stepCompare<T>(System.Collections.Generic.List<T>, System.Collections.Generic.List<T>, System.Comparison<T>, System.Comparison<T>, bool)' ...

Любой способпусть этот метод принимает списки, будь то строки или других классов? Или ярлык для помещения списков строки в тип, который будет принят?

Ответы [ 2 ]

8 голосов
/ 09 мая 2011

Вы не можете заставить string удовлетворить ограничение new(), нет. Хотя string является нормальным классом, и экземпляры могут быть созданы с использованием конструкторов совершенно обычным способом, он не имеет конструктора без параметров.

Лучший подход действительно зависит от , почему у вас была эта строка кода, включая lastItem. Если вам просто нужно какое-то значение по умолчанию, тогда default(T), вероятно, лучший подход.

Если вы действительно делаете , хотите создать новый экземпляр T, то вам, вероятно, следует принять Func<T> в списке параметров метода как способ создания значения по умолчанию по требованию. В качестве альтернативы, если вы довольны использованием определенного единственного значения в качестве значения по умолчанию, вы можете просто добавить параметр типа T. Трудно сказать, не видя остальную часть вашего кода.

6 голосов
/ 09 мая 2011

Если вы хотите любой объект , вам, вероятно, придется жить без new T().Вы можете сделать то же самое с комбинацией рефлексии, особых случаев (для string и т. Д.) И Activator.CreateInstance<T>() - однако, IMO, вы должны ограничить себя (в этом случае) default(T),который будет нулевым для ссылочных типов (включая строку) и обнуляемых типов значений, и все нули для ненулевых типов значений.Возможно, вам также следует использовать bool или аналогичный, чтобы убедиться, что вы на самом деле не используете это значение, за исключением случаев, когда выполняются определенные правила присваивания для компилятора.

...