Investigating your underlying claim
For the purpose of example, let's say that you have a codebase where there is a
MyType class, and there is also some kind of base-type-oriented logic, let's say:
public class MyService
public void DoSomething(MyType b)
So, let's first investigate your claim.
Why can't the compiler/jitter optimize out the call resolutions at compile time?
What you're saying here is that at compile time, your compiler knows that
MyType is never inherited, and therefore it can optimize its compilation based on a
In other words, we can ask ourselves the following question:
Can we have a different type (which derives from
MyType) that the compiler could not have possibly known about at compile time?
If the answer to that question is "no", then your claim is correct. That would mean that the compiler has perfect knowledge of how
MyType is inherited and can therefore optimize the execution based onthat.
If the answer to that question is "yes", then your claim is incorrect. It would mean that the compiler cannot be certain that only
MyType will be used, and therefore it cannot make additional optimizations that are tailored to
Countering your claim
You could probably already see that I'm leading you on a path where the answer to the above question is "yes". That is indeed the case. Let's explore an example use case where the compiler could not have possibly known all of the types in advance.
I'm intentionally not giving examples that have already been given in other answers. There's more than one way in which your claim is not fully correct.
Suppose you compile your library into a DLL. This DLL includes
MyService (which contains the
DoSomething logic). This is now all baked into the DLL and set in stone.
You send me this DLL, and I add it to my own codebase. I end up creating a
MyDerivedType class which derives from
MyType. Due to the rules of inheritance, I am now perfectly allowed to do something like this:
public void MyVeryOwnMethod()
var myService = new MyService();
var myObj = new MyDerivedType();
And there you have it.
DoSomething is being passed an object of type
MyDerivedType, which is not something that your library's compiler would have been able to account for.
If I had referenced your project (i.e. the source code), then my compiler would be able to account for all types, i.e.
MyDerivedType. But this is not how it works when you compile your library as a DLL and then share that DLL (not your source code), and this is a use case that directly goes against your claim that the compiler (of your library code) could have known about all possible types being used to call
Because of this, the compiler knows that it doesn't know all possible types. So when you compile your library code, the compiler doesn't engage in any optimizations that would be based on perfectly knowledge of the whole inheritance graph of
Sealing a class
Your question was about if and how
sealed can add value with regards to compiler optimization.
Let's revise our original example, and let's say that we sealed the
MyType class. Now, the situation has changed. When compiling your library, the compiler is now capable of knowing that it's impossible for any future consumers of this DLL to further derive from it, and therefore the compiler can be confident that it knows the whole
MyType inheritance graph and make optimizations based on that knowledge.
This is how the
sealed keyword can positively impact the compiler's ability to optimize the execution.