Ответ 1
Я бы просто прокомментировал сообщение в leppie, но это было немного длиннее.
В настоящее время я работаю над экспериментальной реализацией CLI. Существует много случаев, когда публично открытый метод (или свойство) не может быть реализован без знания того, как виртуальная машина реализуется внутри страны. Одним из примеров является OffsetToStringData, который требует знания того, как диспетчер памяти выделяет строки.
В таких случаях, когда нет кода С# для выражения метода, вы можете рассматривать каждый вызов метода особым образом, внутренним для процесса JIT. В качестве примера, заменив код call
байтом на ldc.i4
(целое число нагрузки), прежде чем передавать его в генератор нативного кода. Флаг InternalCall
означает "Тело этого метода обрабатывается особым образом самой средой выполнения". Там может быть или не быть реальная реализация - в некоторых случаях в моем коде вызов JACK обрабатывается как intrinsic.
Существуют и другие случаи, когда JIT может иметь специальную информацию, которая позволяет значительно оптимизировать метод. Одним из примеров является метод Math
, хотя даже эти могут быть реализованы на С#, указав InternalCall
, чтобы сделать их эффективно intrinsics, имеет значительный производительности.
В С# метод должен иметь тело, если оно не является abstract
или extern
. extern
означает общий "Вы можете вызывать этот метод из кода С#, но его тело фактически определено в другом месте". Когда JIT достигает вызова метода extern
, он ищет, где найти тело и ведет себя по-разному в результате.
- Атрибут
DllImport
указывает JIT сделать блокировку P/Invoke для вызова реализации собственного кода. - Флаг
InternalCall
указывает JIT обрабатывать вызов определенным образом. - (Есть и другие, но у меня нет примеров с моей головы для их использования.)