2010-04-04 2 views
3

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

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

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

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

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

Вот код Испустите Я использую:

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

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

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

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

+0

Это имеет большой смысл и дает мне представление о том, как реорганизовать мои подпрограммы. Спасибо за совет. – JoeGeeky

0

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

+0

Спасибо, ясно, я неправильно понял, что это значит. В настоящее время это единственное различие между тем, что генерирует VS и генерирует EMIT. Мне нужно вернуться к чертежной доске. – JoeGeeky

0

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

+0

Я пробовал это в режиме выпуска и ничего не менял. Спасибо, хотя ... – JoeGeeky

+0

Ну, почему это проблема, во всяком случае? Два полученных ИЛ равны по эффективности. –