简体   繁体   中英

Why we can’t use sealed classes as generic constraints?

Can you guess what is the reason to not allow sealed classes for type-constraints in generics? I only have one explanation is to give opportunity to use naked constraints.

If the class is sealed it cannot be inherited. If it cannot be inherited it'd be the only type valid for the generic type argument [assuming if allowed to be a type argument]. If it is the only generic type argument then there's no point in making it generic! You can simply code against the type in non-generic class.

Here's some code for this.

public class A
{
    public A() { }
}

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

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

This will give compiler error: 'B' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter.

In addition to this, You can also not have a static class as generic type-constraint. The reason is simple. Static classes are marked as abstract and sealed in compiled IL which can be neither instantiated nor inherited.

Here's the code for this.

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

public static class X
{
}

This will give compiler error: 'X': static classes cannot be used as constraints.

Are you talking about something like this:

class NonSealedClass
{
}

class Test<T> where T : NonSealedClass
{
}

Because it's perfectly legal.

Honestly, I don't quite see the point of it.

As this.__curious_geek points out in his answer , a sealed class cannot be inherited and so using one as a constraint might seem nonsensical.

But there's no guarantee that a sealed class will never be "unsealed" -- ie, that the developer might rearrange its implementation to make it more amenable to inheritance and then remove the sealed modifier from the class definition (or just flat-out remove the sealed keyword for no reason at all).

I know a lot of developers actually encourage this practice: not removing the sealed keyword per se, but rather adding the sealed keyword liberally and only supporting inheritance when the decision to do so is made explicitly (and at this point, yes, removing the sealed keyword).

So I'm not sure why you couldn't use the type of a sealed class as a generic constraint. After all, you could always use the type of a class that just happens to not have any derived classes, even though it's not sealed. The two scenarios don't seem all that different to me.

I'm probably missing something, though. I'm sure Eric Lippert could give a pretty killer explanation.

A naked constraint is where one generic type inherits from another eg

where X:Y

One generic parameter derives from another generic parameter

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

So the class cannot be sealed.

You can also inherit from generics in the normal way so you would not want them sealed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM