3

У меня проблема. Это мой код:C# отражение если: 0 равно 1?

var method = new DynamicMethod("dummy", null, Type.EmptyTypes); 
var g = method.GetILGenerator(); 
g.DeclareLocal(typeof(int)); 

Label inequality = g.DefineLabel(); 
Label equality = g.DefineLabel(); 
Label end = g.DefineLabel(); 

g.Emit(OpCodes.Ldstr, "string"); 
g.Emit(OpCodes.Ldstr, "string"); 
g.Emit(OpCodes.Call, typeof(String).GetMethod("op_Equality", new Type[]{typeof(string), typeof(string)})); 
g.Emit(OpCodes.Stloc_0); 
g.Emit(OpCodes.Ldloc_0); 
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(int)})); 
g.Emit(OpCodes.Ldloc_0); 
g.Emit(OpCodes.Ldc_I4_1); 
g.Emit(OpCodes.Ceq); 
g.Emit(OpCodes.Brtrue_S, equality); 
g.Emit(OpCodes.Brfalse_S, inequality); 
g.MarkLabel(inequality); 
g.Emit(OpCodes.Ldstr, "Specified strings are different."); 
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(string)})); 
g.Emit(OpCodes.Br_S, end); 
g.MarkLabel(equality); 
g.Emit(OpCodes.Ldstr, "Specified strings are same."); 
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); 
g.Emit(OpCodes.Br_S, end); 
g.MarkLabel(end); 
g.Emit(OpCodes.Ret); 

var action = (Action)method.CreateDelegate(typeof(Action)); 
action(); 

Это мой результат:

1 
Specified strings are different. 

Но почему выход неправильно? Команда Ceq сравнивает 1 как результат op_Equation и 0, который находится в верхней части стека. И 1 не равно 0. Так почему это так? Где ошибка? Пожалуйста, помогите мне.

+7

Это ваш третий вопрос по этой теме в последний час. Вы тратите достаточно времени на решение этих проблем самостоятельно? –

+0

У меня нет книг для этого. Я знаю, что это кажется глупым, потому что я использую один и тот же код три раза, но мне нужно знать ответ, и я не знаю, как его решить. Вы можете закрыть его, если хотите, но это нормальный вопрос. Я также могу удалить его и поместить здесь завтра ... – user35443

+1

В нем говорится, что они разные; не то, что вы хотите? – Ryan

ответ

5

После g.Emit(OpCodes.Brtrue_S, inequality); вам нужно перейти к утверждению «равенство» вручную. Иначе он все равно выполнит следующую инструкцию. Так что вам нужно вставить следующую строку после нее:

g.Emit(OpCodes.Br_S, equality); 

Кроме того, это не имеет смысла, чтобы перейти к метке equality, когда он объявлен как следующей инструкции в любом случае. Поэтому удалите это.

поэтому раздел будет выглядеть следующим образом:

g.Emit(OpCodes.Ceq); 

g.Emit(OpCodes.Brtrue_S, inequality); // if true goto inequality 
g.Emit(OpCodes.Br_S, equality); // else goto equality 

g.MarkLabel(inequality);    
g.Emit(OpCodes.Ldstr, "Specified strings are different."); 
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[]{typeof(string)})); 
g.Emit(OpCodes.Br_S, end); // goto end 

g.MarkLabel(equality); 
g.Emit(OpCodes.Ldstr, "Specified strings are same."); 
g.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); 

g.MarkLabel(end); 
g.Emit(OpCodes.Ret); 
4

Ваша ветка относится к метке «неравенство», которая в любом случае следует за утверждением. Итак, независимо от того, вы или нет, это код, который будет вызываться. Вы должны разветвляться на метку «равенство».

Кроме того, ваша линия g.Emit(OpCodes.Brfalse_S, equality); бессмысленна, поскольку она никогда не будет достигнута - вы перепрыгиваете через нее по предыдущему утверждению. И ваш ярлык «неравенства» фактически не будет использоваться нигде, как только логика будет исправлена, поэтому вы также можете помешать этому.

Смежные вопросы