값을 반환하는 메서드가있는 경우 (예를 들어 Remove
메서드 Dictionary
클래스는 bool
을 반환 함) 반환 값을 변수에 할당하지 않으면 어떻게됩니까? 즉, 결과를 bool
변수에 할당하지 않고 dictionary.Remove("plugin-01");
을 작성하면 bool b = dictionary.Remove("plugin-01");
과 관련하여 컴파일의 차이점은 무엇입니까?값을 반환하는 컴파일 된 메서드 호출은 어떻게됩니까?
답변
는 간단한 예제와는 LinqPad의 (의례를 생산하는 IL 코드를 살펴 보자 안전하게 쓸 수
if(!dictionary.Remove("plugin-01")) {
MessageBox.Show("Error: plugin-01 does not exist!");
}
같은 뭔가를 할 수)
void Main()
{
Bar();
Baz();
}
bool Bar()
{
return true;
}
void Baz()
{
Console.WriteLine("placeholder");
}
이 다음과 같은 IL를 생성합니다
IL_0000: ldarg.0
IL_0001: call UserQuery.Bar
IL_0006: pop //remove current value from evaluation stack
IL_0007: ldarg.0
IL_0008: call UserQuery.Baz
Bar:
IL_0000: ldc.i4.1
IL_0001: ret
Baz:
IL_0000: ldstr "placeholder"
IL_0005: call System.Console.WriteLine
IL_000A: ret
Bar
이 호출 된 다음 평가 스택에서 부울 반환 값을 제거하는 팝업이 있습니다. 아무 것도 없습니다. 예제를 업데이트하여 Baz()
에 대한 다른 메서드 호출을 포함 시켜야만했습니다. 그렇지 않으면 프로그램이 끝나기 때문에 팝이 방출되지 않습니다.
void Main()
{
bool foo = Bar();
Console.WriteLine(foo);
}
bool Bar()
{
return true;
}
이것은 다음과 같은 IL을 생성합니다 :
지금 우리가 실제로 반환 값을 사용하는 곳의는 경우를 살펴 보자
IL_0000: ldarg.0
IL_0001: call UserQuery.Bar
IL_0006: stloc.0 //pops current value from evaluation stack, stores in local var
IL_0007: ldloc.0
IL_0008: call System.Console.WriteLine
Bar:
IL_0000: ldc.i4.1
IL_0001: ret
모든 것을있는 System.Console.WriteLine
부분을 무시를 후 IL_007
을 포함하여 - 컴파일러가 변수 사용을 최적화하지 않도록 추가해야했습니다. Bar
메서드 호출의 결과가 평가 스택에서 팝되어 로컬 변수 foo
에 저장되는 것을 볼 수 있습니다. 차이점은 pop
입니다. 반환 값을 가져 오거나 삭제하거나 stloc.0
을 사용하여 결과를 변수에 할당 할 수 있습니다.
따라서 메서드 호출 결과가 필요하지 않으면 결과를 무시해야합니다. 결과를 변수에 할당하고 해당 변수를 사용하지 않더라도 컴파일러는 최소한 변수와 할당을 완전히 최적화 할 수 있습니다 (적어도 디버그 모드에서는 디버깅 환경을 개선하기 위해 대부분의 최적화가 비활성화 됨).
반환 값은 사용하지 않으면 무시됩니다. 당신은 상관하지 않는 경우
당신은
dictionary.Remove("plugin-01");
호출 부분은 동일하지만 할당 부분은 IL에서 건너 뜁니다. 봐 - 여기에 간단한 프로그램의 해체이다
var d = new Dictionary<int,int>();
bool a = d.Remove(5);
d.Remove(6);
디스 어셈블리는 다음과 같습니다
bool a = d.Remove(5);
00000057 mov ecx,dword ptr [ebp-40h]
0000005a mov edx,5
0000005f cmp dword ptr [ecx],ecx
00000061 call 69106A00
// Here is the assignment part
00000066 mov dword ptr [ebp-4Ch],eax
00000069 movzx eax,byte ptr [ebp-4Ch]
0000006d mov dword ptr [ebp-44h],eax
d.Remove(6);
00000070 mov ecx,dword ptr [ebp-40h]
00000073 mov edx,6
00000078 cmp dword ptr [ecx],ecx
0000007a call 69106A00
상위 4 선이 일반적이다가, 첫 번째 호출의 마지막 세 줄은 과제를 처리합니다. 그들은 두 번째 호출에 대한 해체에 빠져 있습니다.
- 1. 연결을 일찍 닫으면 웹 메서드 호출은 어떻게됩니까?
- 2. 값을 반환하는 메서드와 그렇지 않은 메서드
- 3. ItemsControl textbox textchange 이벤트 호출은 어떻게됩니까?
- 4. 바인드 호출은 어떻게됩니까? (python + socket + strace)
- 5. 자동 렌더링 된 객체를 반환하는 클래스 메서드
- 6. EXE 파일의 메서드 호출은 어디에 있습니까?
- 7. RubyMotion에서 파일로드/컴파일 순서는 어떻게됩니까?
- 8. 이 java .execute() 메서드 호출은 무엇을 의미합니까?
- 9. 메서드 호출은 Java의 성능에 어떤 영향을 줍니까?
- 10. 중첩 된 dosync 호출은 어떻게 작동합니까?
- 11. C# - 인터페이스를 반환하는 메서드
- 12. 속성을 반환하는 셀레늄 메서드
- 13. 템플릿 개체의 컴파일 순서는 어떻게됩니까?
- 14. true/false를 반환하는 메서드 적용
- 15. 스텁 OCMock에서 BOOL을 반환하는 메서드
- 16. 호출은
- 17. $ _REQUEST에 값을 할당하면 어떻게됩니까?
- 18. Linq to Sql : 컴파일 된 쿼리 및 확장 메서드
- 19. 다른 값을 반환하는 상속 된 클래스
- 20. INSERT가 포함 된 값을 반환하는 SQL 함수
- 21. 중첩 된 objectForKey 호출은 작동하지만 해당하는 valueForKey 호출은 작동하지 않습니까?
- 22. 동기화 된 메서드 재정의
- 23. executeFetchRequest를 사용하여 객체를 반환하는 메서드
- 24. 여러 값을 반환하는 PHP 스타일
- 25. 0의 수를 반환하는 재귀 메서드
- 26. 임의의 알파벳을 반환하는 확장 메서드
- 27. 토네이도 - GET에서 값을 반환하는 비 차단 통화?
- 28. printf()에 대한 호출은 어떤 값을 생성합니까?
- 29. 어셈블리의 메서드 호출은 .NET에서 해당 소유자의 리플렉션에 의해 생성됩니다.
- 30. 배열로 돌아 오는 목록을 반환하는 웹 메서드
'Console.WriteLine (foo)'를 제거하면 IL이 첫 번째 예제와 동일해야합니까? – enzom83
예 - 그렇습니다. 변수'foo'가 사용되지 않았기 때문에 (아마) 최적화되었습니다. – BrokenGlass
첫 번째 "다음 IL 생성"에서는 통화 다음에 오는 POP 명령을 포함시켜야한다고 생각합니다. 이것은 메소드 결과가 MSIL 스택에 있음을 명확히하고 호출자는 어떻게 든 처리해야합니다 (명시 적으로 "처리"한다고 명시 적으로 버리는 것을 의미 함). –