Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Как выполнить инстанцирование объекта в generic-типе?

#c_sharp


Создаю свой generic-абстрактный класс:    

public abstract class MyAbstractGeneric where 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() (конструктор без параметров). Если нужно передавать в конструктор параметры, то можно добавить защищённый делегат Func createInstance, который будет использоваться для создания экземпляра: //вместо 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}

Комментариев нет:

Отправить комментарий