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)
{
Console.WriteLine(b.CreateMessage());
}
}
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 MyType
-oriented execution.
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 MyType
.
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 MyType
and 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();
myService.DoSomething(myObj);
}
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. MyType
and 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 DoSomething
with.
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 MyDerivedType
.
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.
#[no_mangle]
on a case-by-case basis. Theextern
keyword gives reasonably good FFI (it's much neater than C++'s, imo). (However, you should really ask a separate question if you want to know more; these comments will probably get cleaned up.)sealed
is not explicitly specified. There are packages that can do this automatically.