2012-10-12 27 views

Trả lời

160

Khi bạn có một cá thể đại biểu, bạn có thể biết chính xác loại hoặc bạn có thể chỉ biết rằng đó là Delegate. Nếu bạn biết loại chính xác, bạn có thể sử dụng Invoke, là rất nhanh - mọi thứ đã được xác thực trước. Ví dụ:

Func<int,int> twice = x => x * 2; 
int i = 3; 
int j = twice.Invoke(i); 
// or just: 
int j = twice(i); 

Tuy nhiên! Nếu bạn chỉ biết rằng nó là Delegate, nó phải giải quyết các tham số vv bằng tay - điều này có thể liên quan đến unboxing, vv - rất nhiều sự phản ánh đang diễn ra. Ví dụ:

Delegate slowTwice = twice; // this is still the same delegate instance 
object[] args = { i }; 
object result = slowTwice.DynamicInvoke(args); 

Note Tôi đã viết tay dài args để làm cho nó rõ ràng rằng một object[] là tham gia. Có rất nhiều chi phí phụ trội ở đây:

  • mảng
  • chứng thực đối số được truyền là một "phù hợp" đối với thực tế MethodInfo
  • unboxing vv khi cần thiết
  • phản ánh-gọi
  • thì người gọi cần phải làm điều gì đó để xử lý giá trị trả lại

Về cơ bản, hãy tránh DynamicInvoke khi nào có thể. Invoke luôn thích hợp hơn, trừ khi tất cả bạn có là Delegateobject[].

Đối với một so sánh hiệu suất, sau đây trong chế độ phát hành bên ngoài của debugger (một giao diện điều khiển exe) in:

Invoke: 19ms 
DynamicInvoke: 3813ms 

Code:

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); 
+3

Liệu nó có nghĩa rằng trong trường hợp sử dụng các DynamicInvoke trình biên dịch tạo ra nhiều mã IL để xử lý yêu cầu ủy nhiệm? – testCoder

+1

@testCoder no, nó sẽ sử dụng sự phản chiếu –

+2

Cảm ơn, lời giải thích rất đầy đủ. – testCoder

Các vấn đề liên quan