Что такое MethodImplOptions.InternalCall?
Многие методы в BCL отмечены атрибутом [MethodImpl(MethodImplOptions.InternalCall)]
.
Этот указывает, что "метод реализован в самой общей среде выполнения языка".
Какова была необходимость в разработке структуры таким образом, чтобы указать конкретные инструкции CIL, которые будут принудительно внедрены во время выполнения? В конечном счете, атрибут создает контрактные обязательства для среды выполнения, но таким образом, который кажется мне запутанным и не сразу очевидным.
Например, Math.Pow
мог быть написан таким образом (извините мою неформальную смесь С# + IL и самого IL, если это плохо, это всего лишь образец, чтобы объяснить мою точку зрения):
public static double Pow(double x, double y)
{
ldarg.0
ldarg.1
pow // Dedicated CIL instruction
ret
}
вместо текущего способа:
[MethodImpl(MethodImplOptions.InternalCall)]
public static double Pow(double x, double y);
Почему существует MethodImplOptions.InternalCall
?
Ответы
Ответ 1
Я думаю, что большая причина в том, что создать новую инструкцию IL довольно сложно, и это может повлиять на множество инструментов, включая внешние (ILGenerator
, ilasm, ildasm, PEVerify, Reflector, PostSharp,...).
Но создаем новый метод InternalCall
? Это почти так же просто, как написать метод в С# (я полагаю, я не смотрел на Rotor для проверки), и это ничего не влияет.
И это не только о его создании, я думаю, что то же самое относится и к обслуживанию.
Ответ 2
Я думаю, что это не слишком усложняло CLR. Когда я впервые посмотрел на CIL, я не мог не заметить сходства с языком ассемблера и, более того, ограниченные инструкции, почти как если бы они заставили его работать непосредственно на процессоре.
В теории, когда CLR JIT, что образец кода для Pow
, который вы включили в свой пост, ему придется выдать собственный код для инструкции Pow
, так как нет никакой нативной инструкции (или это? haven с тех пор прошло несколько лет). С точки зрения производительности, но и с точки зрения реализации, гораздо проще просто вызвать mscorlib для кода Pow
, чем просто "вставить" его в строку.
Или у них могла быть таблица поиска для общих функций mscorlib, которые являются InternalCall
и заменяют инструкцию вызовом самой функции. Но опять же, не все InternalCall
так просты.
Я думаю, что это был компромисс для удобства; как на их стороне, так и для удобства обслуживания CLR, более унифицированного стандарта CLI и обеспечения некоторой гибкости для абонентов.
Нижняя строка - это то, что я еще не разработал CLR, и это совсем не в моей голове. Что-то я бы сделал, я думаю.
Ответ 3
Метод является родным, TRULY native, реализованным в самой Runtime. Не забывайте, что CLR происходит от С++. Это как в компиляторе. В реальном мире CIL действительно не выполняется. Он JIT-ted, а затем выполняется, как компилятор, с помощью среды выполнения C/С++. Math.Pow - это, скорее всего, [умозрение] вызов в собственном методе C/С++ math.h pow и его реализация - теперь NET и Mono реализуют CLR.
В UnityEngine.dll [MethodImpl(MethodImplOptions.InternalCall)]
используется для большинства собственных внешних методов. Однако эти С++-методы используют библиотеку CLR Mono С++, и они могут взаимодействовать с С# более интимным способом, чем сам P/INVOKE. И еще более эффективный (PInvoke скрывает некоторые детали реализации и затрудняет понимание)
Однако единственный способ использовать [MethodImpl(MethodImplOptions.InternalCall)]
- это то, что вы являетесь самой средой CLR - я только тестировал Mono, как это. Я не знаю, возможно ли даже изменить реализацию Microsoft CLR, но с Mono вы можете злоупотреблять этой функцией.
Кроме того, не путайте это с [MethodImpl(MethodImplOptions.Unmanaged)]
- это совершенно другая история.
Подробнее о внутренних вызовах и способах работы Mono: http://www.mono-project.com/docs/advanced/embedding/
Отказ от ответственности: Я НЕ отношусь к Unity или Mono!