为什么C#(4.0)不允许generics类型中的共同和逆变?

这种限制的真正原因是什么? 这只是必须完成的工作吗? 概念上难吗? 这不可能吗?

当然,人们不能在字段中使用类型参数,因为它们总是可读写的。 但这不是答案,可以吗?

这个问题的原因是我在C#4上写了一篇关于方差支持的文章,我觉得我应该解释为什么它仅限于委托和接口。 只是为了逆转举证责任。

更新:埃里克问了一个例子。

怎么样(不知道这是否有意义,但是:-))

public class Lookup where T : Animal { public T Find(string name) { Animal a = _cache.FindAnimalByName(name); return a as T; } } var findReptiles = new Lookup(); Lookup findAnimals = findReptiles; 

在一个类中拥有它的原因可能是类本身中保存的缓存。 请不要将您的不同类型的宠物命名为相同!

顺便说一下,这让我想到了C#5.0中的可选类型参数 🙂

更新2:我没有声称CLR和C#应该允许这个。 只是想了解是什么导致它没有。

首先,正如Tomas所说,CLR不支持它。

第二,这将如何运作? 假设你有

 class C { ... how are you planning on using T in here? ... } 

T只能用于输出位置。 如您所知,该类不能包含任何类型为T的字段,因为该字段可以写入。 该类不能有任何采用T的方法,因为它们是逻辑写入的。 假设您有此function – 您将如何利用它?

这对于不可变类是有用的,如果我们可以说,让一个类型为T的只读字段合法; 这样我们就可以大大减少不正确写入的可能性。 但是很难想出其他允许以类型安全方式变化的场景。

如果你有这样的场景,我很乐意看到它。 这将有朝一日在CLR中实现这一点。

更新:见

为什么C#4.0中的类没有通用方差?

关于这个问题的更多信息。

据我所知,CLR不支持此function,因此添加此function也需要在CLR端进行大量工作。 我相信在版本4.0之前CLR实际上支持接口和委托的共同和反向差异,因此这是一个相对简单的实现扩展。

(虽然支持这个类的function绝对有用!)

如果它们被允许,可以定义有用的100%类型安全(没有内部类型转换)类或结构,如果它们的构造函数接受一个或多个T或T供应商,则它们对于它们的类型T是协变的。 可以定义有用的100%类型安全的类或结构,如果它们的构造函数接受一个或多个T消费者,则它们相对于T是逆变的。 我不确定类的优于接口,除了使用“new”而不是使用静态工厂方法(最有可能来自名称类似于接口的类)的能力,但我可以当然看到使用不可变结构支持协方差的用法案例。