【发布时间】:2011-02-02 05:51:30
【问题描述】:
造成这种限制的真正原因是什么?只是必须完成的工作吗?概念上很难吗?不可能吗?
当然,不能在字段中使用类型参数,因为它们始终是可读写的。但这不可能是答案,不是吗?
这个问题的原因是我正在写一篇关于 C# 4 中的方差支持的文章,我觉得我应该解释一下为什么它仅限于委托和接口。只是为了颠倒举证责任。
更新: 埃里克问了一个例子。
这个怎么样(不知道这是否有意义,但是:-))
public class Lookup<out T> where T : Animal {
public T Find(string name) {
Animal a = _cache.FindAnimalByName(name);
return a as T;
}
}
var findReptiles = new Lookup<Reptile>();
Lookup<Animal> findAnimals = findReptiles;
将它放在一个类中的原因可能是类本身中保存的缓存。并且请不要将您不同类型的宠物命名相同!
顺便说一句,这将我带到optional type parameters in C# 5.0 :-)
更新 2: 我没有声称 CLR 和 C# 应该允许这样做。只是试图了解导致它没有的原因。
【问题讨论】:
-
当然,这是一个合理的例子,但你没有展示任何不能用接口完成的事情。只需制作接口 ILookup
并让 Lookup 实现它。您的类差异方案添加了哪些与接口差异相比引人注目的额外好处? -
实际上没有。除此之外,它的代码更少。让我把举证责任倒过来。我们如何解释为什么不支持它。实际上,我并不是要求实施它。 “一直都是这样”不算数! :-)
-
@Eric Lippert:我当然可以想象协变结构的用例。 KeyValuePair
怎么样?可以定义一个 IKeyValPair ,并有一个结构 KeyValPair 来实现它,但这在很多使用场景中都需要非常可怕的装箱。 -
@supercat:这是可以使协变的类型的一个很好的例子。这里的关键是数据类型是逻辑上不可变的,因此您不必担心在构造函数中设置字段后会更改其值。如果我们有 struct 或 class 差异,那就是我想要开始的地方。
-
@Eric Lippert:我知道你讨厌可变结构(顺便说一句,我刚刚打开了一个关于这个主题的聊天室)但是对于结构的协变正确性来说,不变性是必要的吗?传递给期望 IEnumerable
的例程的 List 仍然是 List ,但传递给期望 KeyValuePair 的例程的 KeyValuePair 将 成为 KeyValuePair 。假设 Key 是可变的,那么将 Key 设置为 Dog 会造成什么危害?一种是将狗存放在动物中,而不是猫中。
标签: c# generics c#-4.0 covariance contravariance