简体   繁体   中英

C# reflection if: 0 equals 1?

I have problem. This is my code:

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();

This is my result:

1
Specified strings are different.

But why is output wrong? Ceq instruction is comparing 1 as result from op_Equation and 0 which is on the top of stack. And 1 not equals 0. So why it is? Where is error? Please help me.

After g.Emit(OpCodes.Brtrue_S, inequality); , you need to jump to the "equality" statement manually. Else it will execute the next instruction anyway. So you'll need to insert the following line after it:

g.Emit(OpCodes.Br_S, equality);

Also, it doesn't make sense to jump to the label equality when it is declared as the next instruction anyway. So remove that.

so the section will look like this:

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);

Your branch is to the label "inequality" which immediately follows the statement anyway. So whether you branch or not, this is the code that will be called. You should be branching to the label "equality".

Also, your line g.Emit(OpCodes.Brfalse_S, equality); is pointless as it will never be reached - you jump over it on the preceding statement. And your "inequality" label will not actually be used anywhere once the logic is fixed, so you may as well ditch that too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM