Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I make a type "sealed except for internal types"

I want to make a type that can be inherited from by types in the same assembly, but cannot be inherited from outside of the assembly. I do want the type to be visible outside of the assembly.

Is this possible?

like image 547
Lucas Meijer Avatar asked Jun 18 '10 18:06

Lucas Meijer


People also ask

Can I declare a method as sealed?

A method can also be sealed, and in that case, the method cannot be overridden. However, a method can be sealed in the classes in which they have been inherited. If you want to declare a method as sealed, then it has to be declared as virtual in its base class.

Can base class be sealed?

A sealed class cannot be used as a base class. For this reason, it cannot also be an abstract class.

When would you use a sealed class?

Sealed Classes allow us to fix type hierarchies and forbid developers from creating new subclasses. They are useful when we have a very strict inheritance hierarchy, with a specific set of possible subclasses and no others.

Can you override a sealed class?

You can't inherit from a sealed class, so no inheritance, no override. The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event. When applied to a class, the sealed modifier prevents other classes from inheriting from it.


2 Answers

You can make the constructor internal:

public class MyClass
{
    internal MyClass() { }
}

Every class that derives from a base class must call a constructor of the base class in its constructor. Since it can't call the constructor if the base class is in a different assembly, the derived class doesn't compile.

like image 100
dtb Avatar answered Sep 27 '22 17:09

dtb


I think this question could still benefit from a semantically correct answer... which is "no". You can't declare a type as "sealed to external assemblies only".

Don't get me wrong: dtb's answer is a good one. An internal constructor is the closest you can get from the desired result.

However, I think that anyone reading this should be aware that in this example, MyClass wouldn't be described as being sealed at runtime. It is unlikely that this will ever be a problem, but if may cause logic based on reflection (from your code or a 3rd party library) to act differently on this particular type. It's something to keep in mind.

And now, to further expand on dtb's sample code:

public class MyClass
{
    internal MyClass() { }

    // This factory method will be accessible from external assemblies, making your class instantiable yet still "sealed"
    public static MyClass Create()
    {
        return new MyClass();
    }
}

This way you can still create instances of MyClass from outside the owning assembly, while still keeping control over inheritance.

like image 38
Crono Avatar answered Sep 27 '22 17:09

Crono