---
title: "Why are  sealed classes faster in C#? And should I seal them?"
description: "In C# we can add the `sealed` modifier to a class to indicate that no one is allowed to derive / inherit from that class.\nLet's have a look at the compiler in certain scenarios what happens if you seal a class."
updated: 2022-05-12
tags: ["sealed", "C#", ".NET", "Performance"]
canonical: "https://steven-giesel.com/blogPost/9e7fbbb6-f82a-4ca6-8f6a-b124afc30d48/why-are-sealed-classes-faster-in-c-and-should-i-seal-them"
---

# Why are  sealed classes faster in C#? And should I seal them?

Sealing a class means basically it is forbidden to inherit from that specific class. If you try anyway, you will get a compiler error. This is the main benefit, and you also get some performance improvements with it. This article will show you why plus you get my personal take on `sealed` classes. One word of caution: The performance benefits are very, very small and, in almost all cases, neglectable. You could ask why I am explaining that stuff, then. Well, because I like this nerdy stuff a lot, and I'd like to know what is going on in the runtime when I do certain things.

## `virtual` functions
The reason one would open a class for inheritance is so that someone else can change the behavior of that class and can use it's "internal" state. To offer this we can use the `virtual` function. If you are not familiar with `virtual` functions I got you covered [here](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/virtual).

Why should a sealed class be faster than a class with virtual functions? The answer is simple: We don't have to check which function we have to call. You see if we have something like this: 
```csharp
BaseClass baseClass = new DerivedClass();
baseClass.DoVirtualFunction();
```

The runtime has to check whether it has to call `BaseClass.DoVirtualFunction` or `DerivedClass.DoVirtualFunction()` and this costs time.
If you are interested how this looks in code you can go [here to sharplab.io](https://sharplab.io/#v2:C4LglgNgPgQghgZwKYGEKIQAgEaNehLAXkwDskB3TAESQCcwA3JAEzQwAoBKAbgFgAULmTtCAOmoB7AGpg6wAK5wIAAQCswMJNLd+AgMpJlrUVmTG2BYmUqZDF07sHmIJqxMnrN2pwMEqAZkwVACZMeBErTEEAb0FMBOCgxjlFZWCAFhoZVKVVDS0dLkwYzABfQQq/AUDMF1ZgsNoGZksMTBBwvFNY+MTayWY6BhYkTOzZeTyvQu4S8srBfyD6lka7I1c2wl6BRKTxqRmfYtKqqqA===). 

## `is` and `as`
These two keywords perform a check if we can cast a object to a specific type. Now why should checks against a type have a performance benefit if the type is `sealed`.

Have a look at the following example:
```csharp
public class MyType
{
}

MyType a = CreateMyType();
var isDisposable = a is IDisposable
```

Now pretty obvious that `isDisposable` is always `false`. Unfortunately no it is not. If we extend the example a bit we can see the following:
```csharp
public class MyType { }
public class DerivedType : MyType, IDisposable {}

MyType a = CreateMyType();
var isDisposable = a is IDisposable
```

Then there is a chance that `CreateMyType` returns `DerivedType` which in fact is a `IDisposable`. If we would have a `sealed MyType` we can omit the runtime check because we know at compile-time that this comparison is false.

The performance implications are really small on this one:
```csharp
public class VirtualFunctionBenchmark
{
    private static readonly BaseClass _derivedClass = new DerivedClass();
    private static readonly SealedClass _sealedClass = new();

    [Benchmark]
    public bool Is_NonSealed() => _derivedClass is IDisposable;

    [Benchmark]
    public bool Is_Sealed() => _sealedClass is IDisposable;
}

public class BaseClass { }

public class DerivedClass : BaseClass, IDisposable
{
    public void Dispose() { }
}

public sealed class SealedClass { }
```

Results:
```csharp
|       Method |      Mean |     Error |    StdDev |    Median |
|------------- |----------:|----------:|----------:|----------:|
| Is_NonSealed | 0.0375 ns | 0.0259 ns | 0.0590 ns | 0.0061 ns |
|    Is_Sealed | 0.0061 ns | 0.0092 ns | 0.0082 ns | 0.0024 ns |
```

The check is 5x faster when we handle with a sealed class. But be aware, even the "non-optimized" version is only 0.04 nanoseconds. 

Now the central question: **Should I seal them?**

## `sealed` via default
Now this is my very own personal take and please take it with a grain of salt: I would prefer if classes are `sealed` by default and you have to explicitily allow a class to be inherited from. Why do I say that? Because it gives performance improvements? Well no. Where "free" performance is nice that is not my main take. Getting a proper API design right is not so trivial.  There are many aspects one has to consider when you "open the door" for everyone. I know I am a .NET guy, but still I have to quote from a [Java book](https://www.oreilly.com/library/view/effective-java-2nd/9780137150021/):
> Design and document for inheritance or else prohibit it

And that makes obviously <sup>to me</sup> sense. There are some key features I  do love about `sealed` classes:
* As said, getting the design right is hard. You don't want to have a security class where key details can get overwritten and compromise the security. If you want to have a simpler example: Try to get Equals right with inheritance.
* A non-sealed class CAN'T guarantee immutability.
* Overuse of inheritance. I saw projects with 7 levels of inheritance and a lot of switch cases. Yes that seems counter-intuitive but it exists because it is hard to change the API later on.
* Plays nicely with Composition over inheritance
* Modifying the behavior or structure of your class can potentially break subclasses

But that is just my take on the topic.

## Conclusion
If we use `sealed` type the runtime can remove or simplify some checks for use with which it can give us better performance. But more important with the `sealed` keyword we can express our intend.

