c# - 为什么 C# (4.0) 不允许通用类类型中的协变和逆变?

标签 c# generics c#-4.0 covariance contravariance

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

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

提出这个问题的原因是我正在写一篇关于 C# 4 中的变体支持的文章,我觉得我应该解释一下为什么它仅限于委托(delegate)和接口(interface)。只是为了倒置举证责任。

更新: Eric 问了一个例子。

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

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# 应该允许这样做。只是想了解是什么导致了它没有。

最佳答案

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

其次,这将如何运作?假设你有

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

T只能用在输出位置。正如您所注意到的,该类不能有任何 T 类型的字段,因为该字段可以写入。该类不能有任何采用 T 的方法,因为这些方法在逻辑上是写入的。假设您拥有此功能 - 您将如何利用它?

如果我们可以使具有类型 T 的只读字段合法,那么这对于不可变类将很有用;这样我们就可以大大减少它被不正确写入的可能性。但是很难想出其他允许以类型安全方式进行变化的场景。

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

更新:见

Why isn't there generic variance for classes in C# 4.0?

有关此问题的更多信息。

关于c# - 为什么 C# (4.0) 不允许通用类类型中的协变和逆变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2541467/

相关文章:

c# - 林克异常 : Function can only be invoked from linq to entities

generics - 是否可以自动实现将一个特征对象转换为另一个特征对象的特征?

c# - Directory.EnumerateFiles 和 File.Exists 忽略 native DLL 文件

c# - 如何清空 BlockingCollection

wpf - DataGrid 大小调整问题

c# - 运算符 '??' 不能应用于类型 'T' 和 'T' 的操作数

c# - Activator.CreateInstance 和使用表达式之间有明显的区别吗?

c# - 如何从 f# 返回一个空元组到 c#?

c# - 从 Dictionary<string, object> 中获取值而不拆箱?

java - ChangeListener 作为私有(private)类