The sealed
keyword is one of the very seldom used modifiers in C#. Probably most of you know what it is for, but many developers have not ever used it.
See C# Programmers Guide if you are not sure you remember what the keyword is good for: sealed keyword (MSDN).
Why Shall I Use It?
The most popular, but not really most important motivation is the performance – JIT compiler can produce more efficient code by calling the method non-virtually. I remember someone even made performance measurements, but I think that the real performance gain highly depends on algorithms in a specific use case.
The vast majority of .NET programmers let their classes “unsealed” without even considering making them sealed. If a class was not designedly made inheritable, it is very probably even impossible to inherit from it and override members reasonably. On the other hand, overriding members of the class which were not designed to be overridden might cause unpredictable results.
When a class is originally sealed
, it can change to “unsealed
” in the future without breaking compatibility.
Something New I’ve Discovered Recently
Recently, I was refactoring some component with multiple classes making intensive use of inheritance. During cleanup, I changed all leaf classes in inheritance tree, the classes which cannot be inherited anymore, to be sealed
. I was sure it will not break compatibility, but the next compile failed.
The reason was a bug, which became visible only after I made some class sealed to compile time. Not being sealed
, it would throw an exception during execution. This sample demonstrates the simplified version of this situation:
interface IInterface1 {}
class Class1 {}
class Program
{
static void Main(string[] args)
{
Class1 instanceOfClass1 = new Class1();
IInterface1 someImplementer = (IInterface1)instanceOfClass1;
}
}
Class1
does not implement IInterface1
, however the cast of an instance of the Class1
to IInterface1
does not lead to compilation error. The reason is that theoretically some inherited class of the Class1
might implement this interface.
Now let’s make Class1
sealed. Now the compiler will see that Class1
can be only Class1
“itself” (and its base classes if applicable) and it does not implement interface IInterface1
.
internal interface IInterface1 {}
sealed class Class1 {}
class Program
{
static void Main(string[] args)
{
Class1 instanceOfClass1 = new Class1();
IInterface1 someImplementer = (IInterface1)instanceOfClass1;
}
}
The following compilation error will occur:
Cannot convert type 'Class1' to 'IInterface1'
So using sealed
keyword brings not only performance win and additional code access security but also helps to write bug free code, making better use of the .NET type safety.
My recommendation: Always declare a new class as sealed
until you are writing an abstract
class or a class which must be inherited per design. Most classes in a real application (except you are writing a widely used library) can be made sealed
.
P.S. You can apply the sealed
keyword not only to classes but also to some members. I am going to post about that as well.