문제

Microsoft IL,호출하는 방법에 값을 입력할 필요가 간접 참조.고 말할 수 있습니다 우리는 ILGenerator 라"il"그리고 현재 우리가 널에서 최고의 스택,우리가 원하는 경우 여부를 확인하려면 값은 다음 우리를 방출할 수 있음

var local = il.DeclareLocal(typeof(Nullable<int>));
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ldloca, local);
var method = typeof(Nullable<int>).GetMethod("get_HasValue");
il.EmitCall(OpCodes.Call, method, null);

그러나 그것은 좋은 것을 건너로 저장하는 지역 변수,간단하게 메소드를 호출에는 변수의 주소는 이미 스택에서,다음과 같습니다.

il.Emit(/* not sure */);
var method = typeof(Nullable<int>).GetMethod("get_HasValue");
il.EmitCall(OpCodes.Call, method, null);

이 ldind 가족의 지침 보이는 약속(특히 ldind_ref)그러나 나는 찾을 수 없는 충분한 문서 알아지는 원인이 복싱의 가치,내가 그것을 의심 수도 있습니다.

나는 보 C#컴파일러를 출력하지만,그것을 사용하여 지역 변수를 달성하는 이는 나를 믿는 첫 번째 방법이 될 수 있는 유일한 방법입니다.누군가가 더 좋은 아이디어가?

****편집:추가 정보****

하려고 전화하는 방법을 직접 다음과 같이 프로그램을 선 주석으로,작동하지 않는(오류가 될 것이다"업에 직접 및 간접 런타임").줄의 주석을 제거하고 당신이 볼 수가 예상대로 작동,반"True".

var m = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
var il = m.GetILGenerator();
var ctor = typeof(Nullable<int>).GetConstructor(new[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Newobj, ctor);
//var local = il.DeclareLocal(typeof(Nullable<int>));
//il.Emit(OpCodes.Stloc, local);
//il.Emit(OpCodes.Ldloca, local);
var getValue = typeof(Nullable<int>).GetMethod("get_HasValue");
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(m.Invoke(null, null));

그래서 당신은 단순히 부르는 방법으로 값에 스택기 때문에 값을 입력(비었을 경우 참조 타입)으로 구성되어 있습니다.

내가 무엇을 달성하고 싶(또는지 여부를 알 수 있는 가능)은 대체하는 세 가지로 표시되는 선 주석,하지만 작업 프로그램을 사용하지 않고,임시 로컬입니다.

도움이 되었습니까?

해결책

는 경우는 변수는 이미 스택에서 당신은 가서 수 있고 단지를 방출합니다.

그것은 보인다는 것을 생성자를 하지 않 밀어 스 변수에 입력된 형태입니다.후에 파고 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 방법을 반환 void,그래서 그들은 두지 않는다 그들의 가치에 스택을 같은 다른 방법이 있습니다.그것은 이상하게 보일 수 있는 통화 Setloc 으면 새로운 객체지에서 스택입니다.

다른 팁

후에서 옵션을 더욱 더 고려,나는 당신이 오른쪽에 있다고 가정 할 수 없습니다.당신이 검사를 스택의 행동 MSIL 지침,당신이 볼 수 있는 op 잎이 피연산자(들)을 선택 합니다.가 될 것이기 때문에 요구 사항에 대해'의 주소를 얻는 스택 항목'op,나는 상당히 자신감 하나는 존재하지 않습니다.

로 당신을 떠나 하나 dup+상자 또는 stloc+ldloca.으로 당신이 지적,후자의 가능성이 더 효율적입니다.

@그렉:많은 지침을 떠나 자신의 결과 에 스택,그러나 지나 그들의 피연산자 스택에서 필요한 것에 대한'스 요소의 주소'명령입니다.

나는 알았어요!다행히 나는에 대해 읽기 unbox 사용자는 것으로 나타났 밀어 주소 의 값으로 설정합니다. unbox.any 밀어 실제적인 값입니다.그래서,메소드를 호출에 값을 입력하지 않고 매장에서 지역 변수와 그런 다음 로드 그것의 주소,당신은 단순히 box 다음 unbox.를 사용하여 당신의 마지막 예제:

var m = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
var il = m.GetILGenerator();
var ctor = typeof(Nullable<int>).GetConstructor(new[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Box, typeof(Nullable<int>)); // box followed by unbox
il.Emit(OpCodes.Unbox, typeof(Nullable<int>));
var getValue = typeof(Nullable<int>).GetMethod("get_HasValue");
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(m.Invoke(null, null));

의 단점은 이 복싱 원인 메모리를 할당한 박스형,그들은 그것보다 조금 느리게 사용하여 지역 변수(는 이미 할당).하지만,그것은 당신을 저장 하는 것에서 결정하고,선언,그 참조는 모든 지역 변수는 당신이 필요합니다.

다만을 썼다는 클래스가 무엇이 묻...여기에 IL 코드는 C#컴파일러에서 생성됩니다.

  IL_0008:  ldarg.0
  IL_0009:  ldarg.1
  IL_000a:  newobj     instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_000f:  stfld      valuetype [mscorlib]System.Nullable`1<int32> ConsoleApplication3.Temptress::_X
  IL_0014:  nop
  IL_0015:  ret
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top