Если BaseFruit
есть конструктор, который принимает int weight
, могу ли я создать кусочек фрукта в общем методе, подобном этому?
public void AddFruit<T>()where T: BaseFruit{
BaseFruit fruit = new T(weight); /*new Apple(150);*/
fruit.Enlist(fruitManager);
}
Пример добавлен за комментариями. Кажется, я могу сделать это, только если я дам BaseFruit
конструктор без параметров, а затем заполню все через переменные-члены. В моем реальном коде (не о фруктах) это довольно непрактично.
-Обновление-
Так что кажется, что это никак не может быть решено ограничениями. Из ответов есть три варианта решения:
- Фабричный образец
- отражение
- возбудитель
Я склонен думать, что рефлексия наименее чистая, но я не могу выбирать между двумя другими.
Ответы:
Дополнительно более простой пример:
Обратите внимание, что использование ограничения new () для T только для того, чтобы компилятор проверял открытый конструктор без параметров во время компиляции, фактический код, используемый для создания типа, - это класс Activator.
Вы должны будете убедиться в том, что конкретный конструктор уже существует, и такого рода требования могут быть запахом кода (или, скорее, чего-то, чего вам следует просто избегать в текущей версии на c #).
источник
new object[] { weight }
.CreateInstance
объявляется с параметрами,public static object CreateInstance(Type type, params object[] args)
так что вы можете просто сделатьreturn (T) Activator.CreateInstance(typeof(T), weight);
. Если есть несколько параметров, передайте их как отдельные аргументы. Только если у вас уже есть составное множество параметров, вы можете преобразовать егоobject[]
и передать егоCreateInstance
.Func
который создает новый экземпляр. Предположим,Apple
использование конструктораnew Apple(wgt)
. Затем добавьте кApple
классу это определение:static Func<float, Fruit> CreateOne { get; } = (wgt) => new Apple(wgt);
В Factory определитеpublic static Fruit CreateFruitGiven(float weight, Func<float, Fruit> createOne) { return createOne(weight); }
Usage:Factory.CreateFruit(57.3f, Apple.CreateOne);
-, который создает и возвращаетApple
, сweight=57.3f
.Вы не можете использовать любой параметризованный конструктор. Вы можете использовать конструктор без параметров, если у вас есть "
where T : new()
".Это боль, но такова жизнь :(
Это одна из вещей, которую я хотел бы рассмотреть с помощью «статических интерфейсов» . Затем вы сможете ограничить T включением статических методов, операторов и конструкторов, а затем вызывать их.
источник
Да; измените свое местоположение:
Однако это работает только с конструкторами без параметров . У вас должны быть другие способы настройки вашего свойства (настройка самого свойства или чего-то подобного).
источник
Самое простое решение
Activator.CreateInstance<T>()
источник
Как указал Джон, это жизнь для ограничения беспараметрического конструктора. Однако другое решение заключается в использовании заводского шаблона. Это легко сдерживается
Еще один вариант - использовать функциональный подход. Пройдите в заводском методе.
источник
Вы можете сделать с помощью отражения:
РЕДАКТИРОВАТЬ: Добавлен конструктор == проверка нуля.
РЕДАКТИРОВАТЬ: более быстрый вариант с использованием кэша:
источник
В дополнение к предложению пользователя 1471935:
Чтобы создать экземпляр универсального класса с помощью конструктора с одним или несколькими параметрами, теперь вы можете использовать класс Activator.
Список объектов - это параметры, которые вы хотите указать. По словам Microsoft :
Существует также универсальная версия CreateInstance (
CreateInstance<T>()
), но она также не позволяет вам предоставлять параметры конструктора.источник
Я создал этот метод:
Я использую это таким образом:
Код:
источник
Недавно я столкнулся с очень похожей проблемой. Просто хотел поделиться нашим решением со всеми вами. Я хотел, чтобы я создал экземпляр объекта
Car<CarA>
из объекта json, используя перечисление:источник
Это все еще возможно, с высокой производительностью, делая следующее:
и
Соответствующие классы затем должны наследоваться от этого интерфейса и соответственно инициализироваться. Обратите внимание, что в моем случае этот код является частью окружающего класса, который уже имеет <T> в качестве универсального параметра. R, в моем случае, также является классом только для чтения. ИМО, публичная доступность функций Initialize () не оказывает негативного влияния на неизменяемость. Пользователь этого класса может поместить другой объект, но это не изменит базовую коллекцию.
источник