## Why is this an issue?

Classes and records with either `private` or `file` access modifiers aren’t visible outside of their assemblies or files, so if they’re not extended inside their scope, they should be made explicitly non-extensible with the addition of the `sealed` keyword.

### What is the potential impact?

We measured at least 4x improvement in execution time. For more details see the `Benchmarks` section from the `More info` tab.

## How to fix it

The code can be improved by adding the `sealed` keyword in front of the `class` or `record` types that have no inheritors.

### Code examples

#### Noncompliant code example

    private class MyClass  // Noncompliant
    {
      // ...
    }

    private record MyRecord  // Noncompliant
    {
      // ...
    }

    file class MyClass  // Noncompliant
    {
      // ...
    }

    file record MyRecord  // Noncompliant
    {
      // ...
    }

#### Compliant solution

    private sealed class MyClass
    {
      // ...
    }

    private sealed record MyRecord
    {
      // ...
    }

    file sealed class MyClass
    {
      // ...
    }

    file sealed record MyRecord
    {
      // ...
    }

## Resources

### Documentation

- The `sealed` keyword

### Articles & blog posts

- Boosting Performance With Sealed Classes in .NET
- Performance Improvements in .NET 6

### Benchmarks

Method | Runtime | Mean | Standard Deviation
--- | --- | --- | ---
UnsealedType | .NET 5.0 | 918.7 us | 10.72 us
SealedType | .NET 5.0 | 231.2 us | 3.20 us
UnsealedType | .NET 6.0 | 867.9 us | 5.65 us
SealedType | .NET 6.0 | 218.4 us | 0.59 us
UnsealedType | .NET 7.0 | 1,074.5 us | 3.15 us
SealedType | .NET 7.0 | 216.1 us | 1.19 us

#### Glossary

- Mean
- Standard Deviation

The results were generated by running the following snippet with BenchmarkDotNet:

    [Params(1_000_000)]
    public int Iterations { get; set; }

    private readonly UnsealedClass unsealedType = new UnsealedClass();
    private readonly SealedClass sealedType = new SealedClass();

    [Benchmark(Baseline = true)]
    public void UnsealedType()
    {
        for (int i = 0; i < Iterations; i++)
        {
            unsealedType.DoNothing();
        }
    }

    [Benchmark]
    public void SealedType()
    {
        for (int i = 0; i < Iterations; i++)
        {
            sealedType.DoNothing();
        }
    }

    private class BaseType
    {
        public virtual void DoNothing() { }
    }

    private class UnsealedClass : BaseType
    {
        public override void DoNothing() { }
    }

    private sealed class SealedClass : BaseType
    {
        public override void DoNothing() { }
    }

Hardware Configuration:

    BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2846/22H2/2022Update)
    12th Gen Intel Core i7-12800H, 1 CPU, 20 logical and 14 physical cores
    .NET SDK=7.0.203
      [Host]   : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
      .NET 5.0 : .NET 5.0.17 (5.0.1722.21314), X64 RyuJIT AVX2
      .NET 6.0 : .NET 6.0.16 (6.0.1623.17311), X64 RyuJIT AVX2
      .NET 7.0 : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2