Как работает метод GetILAsByteArray()?

268
10 июля 2018, 06:40

Товарищи, возник следующий вопрос: метод

MethodBody.GetILAsByteArray(); 

возвращает IL-код в байтовом представлении, сие ясно. Однако я не нашел конкретики в описании работы данного метода на MSDN: возвращает ли он "дословную" инструкцию, которую описывал я, либо же эта функция возвращает именно ту инструкцию, которая будет исполняться?

Поясню:

  • В Debug-режиме компилятор никак не оптимизирует код, так что
    исполняемая инструкция идентична той, которую описывал сам
    программист.
  • В Release-режиме же компилятор инлайнит, упраздняет и в целом
    меняет многие вещи, так что конечная исполняемая инструкция может
    серьезно разниться с тем, что изначально описывалось.

Так вот. Влияет ли как-то на GetILAsByteArray() режим компиляции, или же данный метод всегда возвращает "дословную" инструкцию метода?

Answer 1

Влияет ли как-то на GetILAsByteArray() режим компиляции

Ответ - "да". В этом легко убедиться на практике. Напишем тестовый метод:

public void Method(int a, int b)
{    
    string str = (a+b).ToString();
    MessageBox.Show(str);
}

Далее, напишем такой код для извлечения первого операнда из его MSIL-кода и отображения имени операции:

using System;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
...
var mi = this.GetType().GetMethod("Method");
byte[] msil = mi.GetMethodBody().GetILAsByteArray();
ushort op;
if(msil[0]==0xfe) 
    op = (ushort)(msil[1] | 0xfe00);
else 
    op = (ushort)(msil[0]);
//найдем имя операции
string str="";
FieldInfo[] mas = typeof(OpCodes).GetFields();
for(int i=0;i<mas.Length;i++)
{                
    if (mas[i].FieldType == typeof(OpCode))
    {
        OpCode opcode = (OpCode)mas[i].GetValue(null);
        if (opcode.Value == op)
        {
            str = opcode.ToString();
            break;
        }
    }
}
textBox1.Text = "0x"+op.ToString("X4")+": "+str;

Результат:

Debug - 0x0000: nop

Release - 0x0003: ldarg.1

Объясняется это тем, что в отладочной сборке в начале каждого метода вставляется пустой оператор для облегчения отладки (чтобы можно было поставить точку останова на самое начало метода, тогда как в релизной сборке можно только на первую строку). Таким образом, режим компиляции действительно влияет на IL-код метода.

READ ALSO
Как связать две базы

Как связать две базы

Можно ли связать две базы, возможно при помощи оператора where?

265
SLIM ошибка GET-запроса

SLIM ошибка GET-запроса

имеется Url, по которому в мобильном приложении запрашиваю населенные пункты, похожие на строку запроса

241
SLIM SQL запрос

SLIM SQL запрос

Здравствуйте имеется SQL запрос:

339