Как работают виртуальные функции в c#?

244
14 марта 2022, 02:10

Есть ли вообще понятие таблицы виртуальных функций в шарпе? Допустим есть иерархия классов, в классе на вершине иерархии виртуальный метод, который переопределяется в child классах. Методы с середины иерархии с меткой override заносятся в таблицу виртуальных функций? Также интересует заносится ли метод из последнего класса в иерархии?

И наконец, читаю книгу "Clr via c#", до конца не могу понять, сказано, что для структур используется call для вызова функций, т. к. это значимый тип, но структуры также неявно наследуются от System.Object и могут оверрайдить методы, так вот, вопрос, для этих методов используется call или callvirt? Также интересует, когда используется call для вызова виртуальных функций и как работает таблица виртуальных функций для структур, т.к. методы оверрайдятся.

Заранее спасибо за ответы

Answer 1

Есть ли вообще понятие таблицы виртуальных функций в шарпе? Допустим есть иерархия классов, в классе на вершине иерархии виртуальный метод, который переопределяется в child классах. Методы с середины иерархии с меткой override заносятся в таблицу виртуальных функций?

Не столько "виртуальных", сколько просто таблица функций (методов). Каждый тип имеет таблицу методов, которая хранит указатели на дескрипторы всех методов этого класса, как виртуальных, так обычных. В таблицу каждого типа заносится указатель либо на реализацию в этом типе, если это собственный или переопределенный виртуальный метод, либо на одну из реализаций выше по иерархии, если он унаследован. Естественно, каждая реализация будет в какой-то таблице, иначе как ее можно было бы вызвать?

Информацию о структуре таблицы методов можно посмотреть здесь: .NET Framework Internals: How the CLR Creates Runtime Objects - хоть статья и старая, идеи в основном не изменились.

сказано, что для структур используется call для вызова функций, т. к. это значимый тип, но структуры также неявно наследуются от System.Object и могут оверрайдить методы, так вот, вопрос, для этих методов используется call или callvirt? Также интересует, когда используется call для вызова виртуальных функций и как работает таблица виртуальных функций для структур, т.к. методы оверрайдятся

call используется для вызова статического метода, либо для вызова метода экземпляра через раннее связывание (метод известен на этапе компиляции). Метод может быть как виртуальным, так и обычным, и принадлежать как структуре, так и классу. Но если вызвать виртуальный метод через call, virtual dispatch на деле не происходит, т.е. вызов вырождается в невиртуальный.

callvirt используется для вызова методов экземпляра через позднее связывание (метод определяется реальным типом объекта во время выполнения). Метод может быть как виртуальным, так и обычным, и принадлежать как структуре, так и классу. Но для обычного метода позднее связывание, конечно, вырождается в ранее, так как выбирать CLR не из чего (у всех наследников реализация одна и та же).

На практике, компилятор C# генерирует callvirt для вызовов всех виртуальных методов и вызовов обычных методов на классах (последнее связано, насколько я знаю, с лучшей диагностикой вызовов по null-ссылкам). call он генерирует для вызовов статических методов и вызовов обычных методов на структурах.

Следует понимать, что тут много тонкостей, все из которых невозможно описать в рамках ответа. Например, метод, реализующий интерфейс, с точки зрения CLR будет всегда виртуальным, даже если мы об этом не просили, т.е. не пометили его virtual в C#. Кроме того, чтобы callvirt работал со структурами, используется специальный префикс constrained. Полную информацию о внутренней механике CLR и структуре IL-кода можно посмотреть в спецификации ECMA-335 Common Language Infrastructure.

READ ALSO
С# проверка параметров

С# проверка параметров

ПомогитеКак сделать проверку, передается ли в метод хоть какое то числовое значение?

81
Сборка C# проекта через .Net Core SDK 1.1.3 через cmd

Сборка C# проекта через .Net Core SDK 1.1.3 через cmd

Недавно начал курс по Web ,а для сборки задания нуженNet Core SDK 1

97
Растянуть img на всю высоту grid

Растянуть img на всю высоту grid

Откуда эти зазоры? Делал разными способами но они не исчезают

156
Не работает форма отправки

Не работает форма отправки

Скачал готовый шаблон сайта при подключении формы отправки на e-mail возникли проблемы вот код

252