#c_sharp
Создаю свой generic-абстрактный класс: public abstract class MyAbstractGenericwhere T : MyClass { protected T instance; public T MyProp { get { if(instance == null) { instance = new T(); //компилятор не позволяет создавать объект таким образом } return instance; } } } Как правильно инстанциировать объект в таком случае?
Ответы
Ответ 1
Для указания, что параметр T должен иметь конструктор по умолчанию можно использовать ограничение new() Тогда код уже не будет ругаться на new T() Так же в .net присутствует возможность создания объектов с помощью класса Activator Например, Activator.CreateInstance(Type type, params object[] args): instanse = Activator.CreateInstance(typeof(T),parameters);Ответ 2
Как уже сказал Grundy в своём ответе, для того, чтобы компилятор позволил instance = new T();, нужно добавить к ограничениям на тип T наличие new() (конструктор без параметров). Если нужно передавать в конструктор параметры, то можно добавить защищённый делегат FunccreateInstance, который будет использоваться для создания экземпляра: //вместо MyClass я использовал ISerializable, просто чтобы пример был рабочим public abstract class MyAbstractGeneric where T : ISerializable, new() { protected Func createInstance = null; protected T instance; public T MyProp { get { if (instance == null) //используем делегат, если он задан, иначе - конструктор по-умолчанию instance = createInstance == null ? new T() : createInstance(); return instance; } } } И потом, при наследовании, задавать его, например, в конструкторе (либо передавать в конструктор параметром, как это сделано в Lazy ): public class MyStringBuilder : MyAbstractGeneric { public MyStringBuilder() { createInstance = null; } public MyStringBuilder(Func createInstance) { this.createInstance = createInstance; } } И далее: var m = new MyStringBuilder(); var sb = m.MyProp; // -> {} var m2 = new MyStringBuilder(() => { return new StringBuilder("abc"); }); var sb2 = m2.MyProp; // -> {abc}
Комментариев нет:
Отправить комментарий