C#反射if:0等于1?

时间:2012-06-21 14:14:22

标签: c# reflection if-statement reflection.emit system.reflection

我有问题。这是我的代码:

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指令比较op_Equation的结果为1,堆栈的顶部为0。并且1 不等于 0.那么为什么呢?错误在哪里?请帮帮我。

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:4)

你的分支是标签“不平等”,它仍然紧跟在声明之后。因此,无论您是否分支,这都是将被调用的代码。你应该分支到“平等”这个标签。

此外,您的行g.Emit(OpCodes.Brfalse_S, equality);毫无意义,因为它永远无法到达 - 您在前面的语句中跳过它。一旦逻辑修复,你的“不等式”标签实际上不会被用到任何地方,所以你也可以放弃它。