Home > Net >  Does the "Intermediate Language Runtime" (not sure what to call it) enforce sealed classes
Does the "Intermediate Language Runtime" (not sure what to call it) enforce sealed classes

Time:12-22

In C# you can make a class sealed. Then you cannot use that class as a base class for another. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/sealed

Does the "Intermediate Language Runtime" (not sure what to call it) enforce this?

If not, could someone generate Intermediate Language code by hand that derives from a sealed class?

CodePudding user response:

In C# you can make a class sealed. Then you cannot use that class as a base class for another.

Correct.

However, be judicious with the sealed keyword. Don't preemptively add sealed to all of your types without good-cause.

Does the "Intermediate Language Runtime" (not sure what to call it) enforce this?

It's enforced at multiple points, by separate components. I can think of 2 scenarios right now:

  • If you define a class in a C# project that extends a sealed class (either in the same project or in a referenced assembly) then you'll get a compile-time error:

    CS0509 "A sealed class cannot act as a base class.".

  • If you defined a class in a C# project that extends a non-sealed class in a referenced assembly, and then build/compile your project, and then replace the referenced assembly with an updated assembly where the class is now sealed then you'll get a runtime error when the CLR tries to load your derived class (as types are generally loaded on-demand: at the point where they're first-used, this is also when static constructors and type-initializers are invoked):

    Unhandled exception. System.TypeLoadException: Could not load type 'ConsoleApp1.Derived' from assembly 'ConsoleApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the parent type is sealed. at ConsoleApp1.Program.Main(String[] args)

    • The TypeLoadException for this is thrown at the point where a type is loaded, which is nondeterministic. This is why it's a bad idea to replace assemblies/binaries in production without rebuilding the consuming projects from-source to catch these issues beforehand.

Example project:

ConsoleProject1.csproj Program.cs:

namespace ConsoleApp1
{
    public class Derived : ClassLibrary1.SomeClass
    {
        public Derived()
        {
        }
    }

    public static class Program
    {
        static void Main( string[] args )
        {
            ClassLibrary1.SomeClass foo = new Derived();

            Console.WriteLine( "Hello World!" );

            Console.WriteLine( foo.ToString() );
        }
    }
}

LibraryProject.csproj Class1.cs:

namespace ClassLibrary1
{
    public /*sealed*/ class SomeClass // <-- Rebuild this twice, uncommenting the `sealed` keyword for the second build.
    {
    }
}
  • Related