Массив объектов с ошибками, использующий Reflection.Emit - PullRequest
3 голосов
/ 04 апреля 2010

Я пытаюсь выдать то, что, как я думал, будет простым массивом объектов, результатом которого будет код, подобный приведенному ниже примеру

object[] parameters = new object[] { a, b, };

Когда я пишу приведенный выше код на C # с использованием VS, я получаю следующий IL. Как и ожидалось, это работает.

.locals init (
[0] object[] parameters,
[1] object[] CS$0$0000)

Однако, когда я пытаюсь запустить Emit IL напрямую, я получаю только один индексный массив инициализации. Может кто-нибудь помочь мне сказать, где я ошибся?

Вот код Emit, который я использую:

int arraySize = 2;
LocalBuilder paramValues = ilGenerator.DeclareLocal(typeof(object[]));
paramValues.SetLocalSymInfo("parameters");
ilGenerator.Emit(OpCodes.Ldc_I4_S, arraySize);
ilGenerator.Emit(OpCodes.Newarr, typeof(object));
ilGenerator.Emit(OpCodes.Stloc, paramValues);

Вот итоговый IL:

.locals init (
[0] object[] objArray)

Остальная часть полученного IL идентична между двумя решениями, но по некоторым причинам .locals init отличается.

Ответы [ 3 ]

3 голосов
/ 04 апреля 2010

Компилятор C # генерирует код, подобный этому:

object[] temp = new object[2];
temp[0] = (object)a;
temp[1] = (object)b;
parameters = temp;

Переменная temp - это CS $ 0 $ 0000, как вы видите. Я думаю, что это делает это, чтобы исключение, которое может быть вызвано при инициализации массива, не оставляло частично инициализированный массив в «параметрах». Что может вызвать неожиданный сбой, когда код перехватывает исключение. Как написано, именованная переменная либо пуста, либо полностью инициализирована. Хорошая идея.

0 голосов
/ 04 апреля 2010

Переменная CS$0$0000 здесь, потому что компилятор не оптимизировал создание / использование переменных. Он использует эту автоматически созданную переменную для части кода new object[] { a, b, }, а затем назначает созданный объект переменной object[] parameters. Такое поведение в основном из-за стекового характера IL. Попробуйте запустить код в режиме Release и посмотрите, оптимизируется ли он.

0 голосов
/ 04 апреля 2010

Если вы объявите только один локальный (paramValues), то будет объявлен только один локальный. Позвоните DeclareLocal в другой раз, если вам нужен второй местный житель. Но я не понимаю, зачем тебе это? Нет смысла декларировать местных жителей, которые вам не нужны.

...