为什么我们不能使用密封类作为通用约束?

时间:2009-12-22 09:06:45

标签: c# .net generics constraints

你能猜出在泛型中不允许使用密封类进行类型约束的原因是什么?我只有一个解释是给机会使用裸约束。

4 个答案:

答案 0 :(得分:39)

如果课程被密封,则无法继承。如果它不能被继承,它将是泛型类型参数有效的唯一类型[假设允许为类型参数]。如果它是唯一的泛型类型参数,那么将它变为通用就没有意义了!您可以简单地针对非泛型类中的类型进行编码。

以下是一些代码。

public class A
{
    public A() { }
}

public sealed class B : A
{
    public B() { }
}

public class C<T>
        where T : B
{
    public C() { }
}
  

这会给编译器错误:'B'   不是有效的约束。使用的类型   作为约束必须是一个接口,   非密封类或类型   参数

除此之外,您还可以将静态类作为泛型类型约束。原因很简单。 静态类在已编译的 IL 中标记为抽象密封,既不能实例化也不能继承。

以下是此代码。

public class D<T>
        where T : X
{
    public D() { }
}

public static class X
{
}
  

这会给编译器错误:'X':   静态类不能用作   约束

答案 1 :(得分:5)

你在谈论这样的事情:

class NonSealedClass
{
}

class Test<T> where T : NonSealedClass
{
}

因为它完全合法。

答案 2 :(得分:3)

老实说,我不太明白这一点。

作为this.__curious_geek points out in his answer,密封的类不能被继承,因此使用一个作为约束可能似乎无意义。

但是不能保证密封类永远不会“未密封” - 即,开发人员可能会重新安排其实现以使其更适合继承,然后从类定义中删除sealed修饰符(或者只是简单地删除sealed关键字,完全没有理由。

我知道很多开发人员实际上都鼓励这种做法:不要删除sealed关键字本身,而是大量添加 sealed关键字,并且只支持继承这样做的决定是明确的(在这一点上,是的,删除sealed关键字)。

所以我不确定为什么你不能使用密封类的类型作为通用约束。毕竟,你总是可以使用恰好没有任何派生类的类的类型,即使它没有被密封。这两种情况似乎与我没有什么不同。

但是,我可能会遗漏一些东西。我确信Eric Lippert可以给出一个相当杀手级的解释。

答案 3 :(得分:1)

裸约束是一个泛型类型从另一个继承的地方,例如

where X:Y

一个通用参数派生自另一个通用参数

class Foo<T>
{
    Foo<S> SubsetFoo<S>() where S : T {  }
}

因此课程无法封存。

您也可以以正常方式继承泛型,这样您就不会希望它们被密封。