你能猜出在泛型中不允许使用密封类进行类型约束的原因是什么?我只有一个解释是给机会使用裸约束。
答案 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 { }
}
因此课程无法封存。
您也可以以正常方式继承泛型,这样您就不会希望它们被密封。