C# 为什么我们可以’;不使用密封类作为泛型约束?

C# 为什么我们可以’;不使用密封类作为泛型约束?,c#,.net,generics,constraints,C#,.net,Generics,Constraints,您能猜出在泛型中不允许类型约束使用密封类的原因吗?我只有一个解释,那就是给机会使用裸约束。你是说这样的事情吗: class NonSealedClass { } class Test<T> where T : NonSealedClass { } 类非密封类 { } 类别测试,其中T:非密封类别 { } 因为它是完全合法的。如果类是密封的,它就不能被继承。如果它不能被继承,那么它将是泛型类型参数的唯一有效类型[假设它被允许是类型参数]。如果它是唯一的泛型类型参数,那么将其变为泛

您能猜出在泛型中不允许类型约束使用密封类的原因吗?我只有一个解释,那就是给机会使用裸约束。

你是说这样的事情吗:

class NonSealedClass
{
}

class Test<T> where T : NonSealedClass
{
}
类非密封类
{
}
类别测试,其中T:非密封类别
{
}

因为它是完全合法的。

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

这里有一些代码

public class A
{
    public A() { }
}

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

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

public static class X
{
}
公共A类
{
公共A(){}
}
B类公共密封:A类
{
公共B(){}
}
公共C类
其中T:B
{
公共C(){}
}
这将导致编译器错误:'B' 不是有效的约束。使用的类型 因为约束必须是一个接口, 非密封类或类型 参数。

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

这是代码

public class A
{
    public A() { }
}

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

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

public static class X
{
}
公共类D
其中T:X
{
公共D(){}
}
公共静态类X
{
}
这将导致编译器错误:'X': 静态类不能用作 限制条件。


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

where X:Y
一个泛型参数派生自另一个泛型参数

class Foo<T>
{
    Foo<S> SubsetFoo<S>() where S : T {  }
}
class-Foo
{
Foo SubsetFoo()其中S:T{}
}
所以这个类不能被密封


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

老实说,我不太明白这有什么意义

例如,一个密封的类不能被继承,因此使用一个类作为约束可能看起来是毫无意义的

但是不能保证一个密封的类永远不会被“解封”——也就是说,开发人员可能会重新安排它的实现,使其更易于继承,然后从类定义中删除
sealed
修饰符(或者干脆毫无理由地删除
sealed
关键字)

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

所以我不确定为什么不能使用密封类的类型作为泛型约束。毕竟,您总是可以使用碰巧没有任何派生类的类的类型,即使它不是密封的。这两种情况在我看来并没有什么不同


不过,我可能遗漏了什么。我肯定可以给出一个很好的解释。

List x=…
在泛型约束中使用了非密封的
按钮
类,但我不确定这是您想要问的问题。你能澄清你的问题吗?我想你需要重新表述问题的标题。它应该是“为什么我们不能使用密封类作为泛型约束?”如果你能在问题中加入一些代码示例,这将非常有用。我在回答中添加了一些代码。这可能会有帮助。@Juliet:在您的示例中,
按钮是一个类型参数,而不是约束。泛型是一种普遍使用算法并获得更好性能的方法。所以我有点不同意你关于继承的观点。但是现在绝对有一种方法,你可以实例化C以外的任何类型的C对象。因为B是密封的,所以它不能有子类,所以没有其他类型可以匹配“where T:B”。因此,T型始终为B型;否则,约束将失败。如果您的泛型代码受到约束,因此只能应用于一种类型,那么它仍然是泛型的吗?:)顺便说一句,如果一个类有两个泛型类型参数,其中一个从另一个继承,那么两个参数都是同一个密封类是完全可以接受的。即使第二个参数是密封类这一事实意味着第一个参数必须是同一个密封类,也没有编译器的抱怨。我认为投诉的基本原因是鼓励人们不要使用泛型类型参数,因为泛型类型参数只能是一种类型。如果使用多个约束,情况会怎样?例如,如果两个约束都有相似的方法/成员,但实际上没有继承同一个类或使用公共接口,那么您的选择是什么?他提到使用非密封类作为泛型约束,我猜他可能是指一个封闭的班级…这似乎是一个延伸。。。在某种程度上,这是一个问题,为什么不能在非泛型方法上利用多态性呢?通常,当涉及到编译时检查时,编译代码的每一位都被认为处于当前状态。是的,一个密封的类将来可能会被解封,所以编译器可能不应该输出错误。但是,也许其他方法将来会得到一个带有额外参数的重载,也许将来会添加未知类-这是否意味着所有这些编译器错误都应该被抑制,只是因为相应的代码行在将来会有意义吗?但我希望S是T类型的。不要继承。您可以使用类或接口类型