3

문제가 있습니다. 이건 내 코드입니다 :C# reflection if : 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 과 같지 않습니다. 그렇다면 이유는 무엇입니까? 오류가 어디 있습니까? 도와주세요.

+7

이 마지막 시간에이 주제에 대한 3 번째 질문이다. 이 문제를 스스로 해결하는 데 충분한 시간을 할애하고 있습니까? –

+0

나는 이것에 대한 책을 가지고 있지 않습니다. 같은 코드를 세 번 사용하기 때문에 어리 석다는 것을 알지만 대답을 알아야하고 해결 방법을 모르겠습니다. 원한다면 닫을 수 있지만 정상적인 질문입니다. 나는 그것을 삭제하고 내일 여기에 놓을 수있다. ... – user35443

+1

그것은 그들이 다르다고 말한다; 너가 원하는게 아니야? – Ryan

답변

5

g.Emit(OpCodes.Brtrue_S, inequality); 다음에 "equality"문으로 수동으로 이동해야합니다. 그렇지 않으면 어쨌든 다음 명령을 실행합니다. 그래서 당신은 그 뒤에 다음 줄을 삽입해야합니다 :

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); 라인에는 도달하지 않으므로 아무런 의미가 없습니다. 논리가 고정되면 "불평등"레이블이 실제로는 사용되지 않으므로 그렇게해도됩니다.