델리게이트에서 Invoke와 DynamicInvoke의 차이점은 무엇입니까? 이 두 방법의 차이점을 설명하는 코드 예제를 알려주십시오.
답변
델리게이트 인스턴스가있는 경우 정확한 유형을 알거나 해당 유형이임을 알 수 있습니다 Delegate
. 정확한 유형을 알고 있다면을 사용할 수 있습니다 Invoke
. 매우 빠릅니다 . 모든 것이 이미 사전 검증되었습니다. 예를 들면 다음과 같습니다.
Func<int,int> twice = x => x * 2;
int i = 3;
int j = twice.Invoke(i);
// or just:
int j = twice(i);
하나! 당신이 그것을 알고 있다면 Delegate
, 매개 변수 등을 수동으로 해결해야합니다-이것은 unboxing을 포함 할 수 있습니다. 예를 들면 다음과 같습니다.
Delegate slowTwice = twice; // this is still the same delegate instance
object[] args = { i };
object result = slowTwice.DynamicInvoke(args);
참고 사항 이 포함되어 args
있음을 분명히하기 위해 긴 손을 썼습니다 object[]
. 여기에 많은 추가 비용이 있습니다 :
- 배열
- 전달 된 인수의 유효성을 검사하는 것이 실제에 “적합한”
MethodInfo
- 필요에 따라 개봉 등
- 반사 호출
- 호출자는 반환 값을 처리하기 위해 무언가를해야합니다.
기본적으로 가능 DynamicInvoke
하면 항상 피하십시오 . Invoke
모든 것이 a Delegate
및 a가 아닌 한 항상 선호 object[]
됩니다.
성능 비교를 위해 디버거 외부의 릴리스 모드 (콘솔 exe)에서 다음이 인쇄됩니다.
Invoke: 19ms
DynamicInvoke: 3813ms
암호:
Func<int,int> twice = x => x * 2;
const int LOOP = 5000000; // 5M
var watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
twice.Invoke(3);
}
watch.Stop();
Console.WriteLine("Invoke: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
twice.DynamicInvoke(3);
}
watch.Stop();
Console.WriteLine("DynamicInvoke: {0}ms", watch.ElapsedMilliseconds);