背景:我想“扩展”.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>
to的实例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 无法识别类定义中的变体泛型类型,还有哪些其他方法可以使其与可接受的 OO 实践更加一致?我想我不是唯一面临这个问题的人,所以希望能对此有所了解。