Marius Schulz
Marius Schulz
Front End Engineer

Combining Modifiers in C#: "protected internal" and "override sealed"

There are a variety of modifiers in C# that can be used to modify types and type members. I'm of course talking about the following list:

  • abstract
  • async
  • const
  • event
  • extern
  • in
  • internal
  • new
  • out
  • override
  • partial
  • private
  • protected
  • public
  • readonly
  • sealed
  • static
  • unsafe
  • virtual
  • volatile

Now that we're on the same page, let's take a look at two lesser-known combinations of two modifier keywords that result in slightly different behavior.

#Granting Access (Or Not)

You all know the four access modifiers:

  • internal: accessible within same assembly
  • private: only accessible within same class
  • protected: accessible within same class or derived classes
  • public: accessible without restrictions

That's nothing new so far. But did you know you can combine the protected and internal keywords to get the protected internal modifier? A member that has the protected internal access modifier is accessible within the same assembly or from within a derived type. Note that this is a disjunctive composition: It's perfectly legal to satisfy only one of the two conditions.

#Overriding Members (Or Not)

Another lesser-known combination of modifiers is override sealed. While override denotes a new implementation of an inherited virtual member, sealed prevents a class from being inherited from.

That's not the only use case for sealed, though: If a method or property already has the override modifier, it can also receive the sealed modifier; that specific member then cannot be overriden in any more derived classes:

public class A
{
    protected virtual void Foo() { }
    protected virtual void Bar() { }
}

public class B : A
{
    // Prevent further overrides
    protected override sealed void Foo() { }
}

public class C : B
{
    // OK, overriding Bar is legal
    protected override void Bar() { }

    // Error: "cannot override inherited member `B.Foo'
    // because it is sealed"
    protected override void Foo() { }
}

Do you have any other modifier combinations that you feel too few developers know about? If yes, please share them in the comments!