Как разрешить перегрузку инициализатора по умолчанию для помощника геттера

Я решил добавить пользовательские вспомогательные функции Get/SetValue (с INotifyPropertyChanged) в мой ViewModelBaseClass, похожие на безопасный метод, упомянутый здесь. Но я хочу добавить необязательный инициализатор в вспомогательную функцию Get, которая имеет разумные значения по умолчанию. К сожалению, ключевое слово по умолчанию инициализирует ссылочные типы значением null, типы значений, допускающие значение NULL, значением null, а типы значений значением по умолчанию.

Я хочу создать общую функцию, которая будет вызываться помощником Get, который возвращает значения по умолчанию для типов, значения значений по умолчанию для BaseType для Nullable (если возможно) и конструкторы по умолчанию для ссылочных типов, у которых есть конструкторы по умолчанию. Я думаю, что для ссылочных типов, которые не реализуют конструктор, он может возвращать значение null. Но выяснить, как вызывать new T() vs default(T) в if else сложно, компилятор говорит, что у него нет правильных ограничений (потому что, конечно, ограничения проверяются во время выполнения).

В качестве альтернативы я мог бы использовать http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx в вспомогательном методе Get (о котором он сказал:

Это, возможно, самый ужасный код, который я когда-либо писал.

Пожалуйста, пожалуйста, не используйте его в реальной жизни. Используйте разные имена методов или что-то в этом роде. Тем не менее, это забавная маленькая головоломка, не так ли?

) в качестве преимущества это могло бы позволить мне заставить ссылочные типы без конструкторов по умолчанию указывать необязательный init Func.


person Roman A. Taycher    schedule 02.01.2013    source источник


Ответы (1)


Вы можете попробовать этот метод. Кажется, я не мог найти лучшего способа вернуть значение по умолчанию для базового типа типа, допускающего значение NULL. Я буду продолжать искать и обновлять свой пост, если я что-то найду. Однако вы не можете передавать ссылочные типы без конструктора без параметров.

static T GetDefault<T>() where T : new()
{
    var type = typeof (T);
    var underlying = Nullable.GetUnderlyingType(type);
    if (underlying != null)
        return (T) Activator.CreateInstance(underlying);
    return new T();
}

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

static T GetDefault<T>()
{
    var type = typeof (T);
    var underlying = Nullable.GetUnderlyingType(type);
    if (underlying != null)
        return (T) Activator.CreateInstance(underlying);
    var constructor = type.GetConstructor(Type.EmptyTypes);
    return (T) (constructor == null ? default(T) : Activator.CreateInstance(type));
}
person Mir    schedule 02.01.2013