代码之家  ›  专栏  ›  技术社区  ›  Lars Corneliussen

为什么C(4.0)不允许泛型类类型中的协变和逆变?

  •  22
  • Lars Corneliussen  · 技术社区  · 15 年前

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

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

    这个问题的原因是我在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应该允许这样做。只是想了解是什么导致了这一切。

    3 回复  |  直到 13 年前
        1
  •  20
  •   Community CDub    8 年前

    首先,正如托马斯所说,它在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?

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

        2
  •  8
  •   Tomas Petricek    15 年前

    据我所知,clr不支持此功能,因此添加此功能也需要在clr端进行大量工作。我相信在4.0版本之前,clr实际上支持接口和委托的协变和逆变,所以这是一个相对简单的实现扩展。

    (尽管如此,为类支持这个特性绝对是有用的!)

        3
  •  1
  •   supercat    13 年前

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