一个原因是:
class Foo<out T>
{
T _store;
public T Get()
{
_store = default(T);
return _store;
}
}
这个类包含一个非协变的特性,因为它有一个字段,并且字段可以设置为值。它虽然以协变方式使用,因为它只被分配了默认值,并且只适用null
于实际使用协变的任何情况。
因此,尚不清楚我们是否可以允许它。不允许它会激怒用户(它毕竟符合您建议的相同潜在规则),但允许它是困难的(分析已经变得有点棘手,我们甚至没有开始寻找真正棘手的案例)。
另一方面,对此的分析要简单得多:
void Main()
{
IFoo<object> foo = new Foo<string>();
Console.WriteLine(foo.Get());
}
interface IFoo<out T>
{
T Get();
}
class Foo<T> : IFoo<T>
{
T _store;
public T Get()
{
_store = default(T);
return _store;
}
}
很容易确定没有任何实现会IFoo<T>
破坏协方差,因为它没有。所需要做的就是确保没有使用T
用作参数(包括 setter 方法的参数)并且它已经完成。
由于类似的原因,类的潜在限制比接口上的潜在限制要困难得多,这一事实也降低了协变类的有用程度。它们当然不会毫无用处,但是它们的有用性与指定和实施关于它们将被允许做什么的规则的工作量之间的平衡远小于协变接口的有用性之间的平衡。关于指定和实施它们的工作量。
当然,差异已经足够,以至于它已经过了“好吧,如果你要允许 X 不允许 Y ......”的观点。