以这个小的LINQPad为例:
void Main()
{
Foo<object> foo = new Foo<string>();
Console.WriteLine(foo.Get());
}
class Foo<out T>
{
public T Get()
{
return default(T);
}
}
它无法编译这个错误:
方差修改器无效。只有接口和委托类型参数可以指定为变体。
为什么这是不允许的呢?
其中一个原因是:
class Foo<out T>
{
T _store;
public T Get()
{
_store = default(T);
return _store;
}
}
因此,我们是否可以允许它并不清楚。不允许它会刺激用户(它毕竟符合你建议的相同的潜在规则),但允许它很困难(分析已经有点棘手了,我们甚至没有开始寻找真正棘手的情况)。
另一方面,对此的分析要简单得多:
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;
}
}
由于类似原因,潜在的限制在类上比在界面上要困难得多,这也降低了协变类有用的程度。它们当然不会是无用的,但是平衡指定和实现有关允许执行什么规则的工作量是多么有用,远远低于协变接口的有用程度的平衡了解指定和实施它们的工作量。
一个类只需要包含输出方法参数和只有输入方法参数。重点是很难保证类:例如,协变类(通过T类型参数)不能有字段T,因为你可以写入这些字段。它对于真正不可变的类很有用,但目前还没有全面支持C#的不变性。