private void AMethod<T>() where T : Control, new()
{
Lazy<T> lazyControl = new Lazy<T>(() => new T());
Lazy<Control> a = lazyControl;
}
我在最后一行收到以下错误。
Argument 2: cannot convert from 'System.Lazy<T>' to
'System.Lazy<System.Windows.Forms.Control>'
我知道T可以是更具体的类型,但是我不明白为什么不能将其分配给Lazy变量。
答案 0 :(得分:4)
我知道
T
可以是更具体的类型,但是我不明白为什么不能将其分配给Lazy变量。
Lazy<T>
与Lazy<Control>
没有任何关系,与Lazy<Base>
与Lazy<Derived>
没有任何关系一样。
仅由于Derived
源自Base
,您可以执行以下操作:
Base b = new Derived();
...这并不意味着您可以这样做:
Lazy<Base> b = new Lazy<Derived>();
类型Lazy<Derived>
并非源自Lazy<Base>
。 @Jon Skeet在这里对此进行了很好的解释:
答案 1 :(得分:3)
如果有一个ILazy<T>
接口,则可以将其声明为ILazy<out T>
,在您的示例中一切都会很好:T
仅有效地处于输出位置。
但是,Lazy<T>
是一个类。只能为委托和接口指定协方差/协方差,因此Lazy<T>
无法指定其协方差。
因此,Lazy<Control>
与Lazy<T>
不兼容,这就是分配不起作用的原因。从调用者的角度来看,至少对于当前的API而言,协变是“安全的”。
(如果您到处都需要它,则可以声明自己的ILazy<out T>
接口,然后编写该接口的实现来包装Lazy<T>
。我怀疑这样做的麻烦多于其价值。 )