Предпосылки: я хотел «расширить» тип .NET Lazy<>
для поддержки неявного преобразования между Lazy<T>
и нижележащим объектом T
, чтобы иметь возможность автоматически разворачивать содержащееся значение. Мне это удалось довольно легко:
public class ExtendedLazy<T> : Lazy<T>
{
public ExtendedLazy() : base() {}
public ExtendedLazy(bool isThreadSafe) : base(isThreadSafe) { }
public ExtendedLazy(Func<T> valueFactory) : base(valueFactory) { }
// other constructors
public static implicit operator T(ExtendedLazy<T> obj)
{
return obj.Value;
}
}
Я хотел пойти дальше, сделав T
ковариантным, чтобы можно было назначить экземпляр ExtendedLazy<Derived>
ExtendedLazy<Base>
. Поскольку модификаторы дисперсии не допускаются в определениях классов, для этого мне пришлось прибегнуть к пустому интерфейсу:
public interface IExtendedLazy<out T>
{
}
И изменил определение моего класса на
public class ExtendedLazy<T> : Lazy<T>, IExtendedLazy<T>
Это отлично работает, и я смог использовать этот ковариантный тип:
ExtendedLazy<DerivedClass> derivedLazy = new ExtendedLazy<DerivedClass>();
IExtendedLazy<BaseClass> baseLazy = derivedLazy;
Хотя это компилируется и работает нормально, оно противоречит CA1040: избегайте пустых интерфейсов в котором говорится, что использование пустых интерфейсов в качестве контрактов - это плохой дизайн и неприятный запах кода (и я уверен, что большинство людей с этим согласны). Мой вопрос: учитывая неспособность среды CLR распознавать вариативные универсальные типы в определениях классов, какие еще способы сделать это более согласованным с приемлемыми практиками объектно-ориентированного программирования? Я полагаю, что я не единственный, кто сталкивается с этой проблемой, поэтому я надеюсь получить некоторое представление об этом.
T Value { get; }
участника в любом случае. - person Lucas Trzesniewski   schedule 02.10.2015static ConcurrentDictionary<Type, bool>
вместе с вызовами отражения, когда я могу добиться того же с помощью оператораis
в одном выражении? И это все еще быстрее, чем поиск в кеше. - person Lucas Trzesniewski   schedule 02.10.2015