Действительно ли возможно косвенно загрузить тип значения на стеке

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

7
задан Greg Beech 17 September 2008 в 18:26
поделиться

2 ответа

Если переменная уже находится на стеке, можно идти вперед и просто испустить вызов метода.

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

Можно загрузить переменную, которая сохранит ссылку на стопку оценки прежде, чем вызвать конструктора и затем загрузит ту переменную снова после вызова конструктора как так:

DynamicMethod method = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
ILGenerator il = method.GetILGenerator();
Type nullable = typeof(Nullable<int>);
ConstructorInfo ctor = nullable.GetConstructor(new Type[] { typeof(int) });
MethodInfo getValue = nullable.GetProperty("HasValue").GetGetMethod();
LocalBuilder value = il.DeclareLocal(nullable);         

// load the variable to assign the value from the ctor to
il.Emit(OpCodes.Ldloca_S, value);
// load constructor args
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Call, ctor);
il.Emit(OpCodes.Ldloca_S, value);

il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(method.Invoke(null, null));

Другая опция делает его способ, которым Вы показали. Единственная причина этого, что я вижу, состоит в том, что ctor методы возвращаются пусто, таким образом, они не помещают свое значение на стек как другие методы. Действительно кажется странным, что можно назвать Setloc, если новый объект не находится на стеке.

2
ответ дан 7 December 2019 в 14:39
поделиться

После рассмотрения опций еще немного и дальнейшее соображение, я думаю, что Вы правы в предположении, что оно не может быть сделано. При исследовании поведения стека инструкций MSIL Вы видите, что никакой op не оставляет свой операнд (операнды) на стеке. Так как это было бы требованием для, 'получают адрес записи стека' op, я - довольно уверенный, не существует.

Это оставляет Вас или с dup+box или с stloc+ldloca. Как Вы указали, последний, вероятно, более эффективен.

@greg: Много инструкций оставляют свой результат на стеке, но никакие инструкции не оставляют ни одного из своих операндов на стеке, который требовался бы для, 'получают инструкцию по ' адреса элемента стека.

1
ответ дан 7 December 2019 в 14:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: