В случае, если у вас есть виртуальный метод в запечатанном классе, а типом ссылки на объект является запечатанный класс, виртуального вызова можно было бы избежать. Возьмите следующий пример. Нет никакой фактической причины, по которой GetName нужно вызывать виртуально, потому что мы знаем, что не может быть подкласса Parent и, следовательно, никакой дальнейшей виртуальной отправки.
sealed class Parent : Child {
public override string GetName() { return "foo"; }
}
public void Test() {
var p = new Parent();
var name = p.GetName();
}
Компилятор мог бы заметить это и вывести инструкцию call IL вместо callvirt. Однако и C #, и VB.Net Compiler решили не выполнять эту оптимизацию. Оба будут испускать callvirt.
JIT также свободен для такой оптимизации. Он также решает не делать этого.
Это не значит, однако, что вы не должны закрывать свои уроки. Классы должны быть запечатаны, если вы на самом деле не собираетесь кому-то наследовать от них. В противном случае вы открываете себя для сценариев, которые вы точно не оценили.
Кроме того, ничто не мешает компиляторам и JIT реализовать это позднее.