2010-09-29 23 views
9

Tôi đã nhận thấy một số ví dụ về những thứ hoạt động và không hoạt động khi xử lý các hàm lambda và các đại biểu ẩn danh trong C#. Những gì đang xảy ra ở đây?Làm cách nào để nhập và ủy quyền đại biểu/lambda?

class Test : Control { 
    void testInvoke() { 
     // The best overloaded method match for 'Invoke' has some invalid arguments 
     Invoke(doSomething); 

     // Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type 
     Invoke(delegate { doSomething(); }); 

     // OK 
     Invoke((Action)doSomething); 

     // OK 
     Invoke((Action)delegate { doSomething(); }); 

     // Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type 
     Invoke(() => doSomething()); 

     // OK 
     Invoke((Action)(() => doSomething())); 
    } 

    void testQueueUserWorkItem() { 
     // The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments 
     ThreadPool.QueueUserWorkItem(doSomething); 

     // OK 
     ThreadPool.QueueUserWorkItem(delegate { doSomething(); }); 

     // The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments 
     ThreadPool.QueueUserWorkItem((Action)doSomething); 

     // No overload for 'doSomething' matches delegate 'WaitCallback' 
     ThreadPool.QueueUserWorkItem((WaitCallback)doSomething); 

     // OK 
     ThreadPool.QueueUserWorkItem((WaitCallback)delegate { doSomething(); }); 

     // Delegate 'WaitCallback' does not take '0' arguments 
     ThreadPool.QueueUserWorkItem(() => doSomething()); 

     // OK 
     ThreadPool.QueueUserWorkItem(state => doSomething()); 
    } 

    void doSomething() { 
     // ... 
    } 
} 

Vâng, đó là rất nhiều ví dụ. Tôi đoán câu hỏi của tôi như sau:

  1. Tại sao Invoke luôn từ chối một hàm lambda hoặc một đại biểu vô danh, nhưng ThreadPool.QueueUserWorkItem không chỉ tốt?

  2. Heck làm gì "Không thể chuyển đổi phương thức ẩn danh để nhập 'System.Delegate' vì nó không phải là loại đại biểu" có nghĩa là gì?

  3. Tại sao ThreadPool.QueueUserWorkItem chấp nhận một đại biểu ẩn danh không có tham số, nhưng không chấp nhận biểu thức lambda không có tham số?

Trả lời

9
  1. ThreadPool.QueueUserWorkItem có một cụ đại biểu trong chữ ký của mình; Gọi chỉ có Delegate. Các biểu thức lambda và các phương thức nặc danh chỉ có thể được chuyển đổi thành một loại đại biểu cụ thể.

  2. Nó chỉ là một thông báo lỗi xấu. Nó có nghĩa là, "Tôi không biết chính xác loại đại biểu bạn đang cố gắng chuyển đổi."

  3. Bạn đang sử dụng một phương thức ẩn danh không có danh sách tham số ở tất cả có thể được chuyển đổi thành bất kỳ loại đại biểu nào không sử dụng tham số out/ref. Nếu bạn đã thử delegate() { ... } (nghĩa là danh sách tham số rỗng trống) thì nó sẽ không hoạt động. Khả năng "Tôi không quan tâm đến các tham số" của các phương thức ẩn danh là chỉ tính năng mà chúng có biểu thức lambda không.

Đó là đơn giản nhất để chứng minh tất cả điều này trong bối cảnh của bài tập đơn giản, IMO:

// Doesn't work: no specific type 
Delegate d =() => Console.WriteLine("Bang"); 

// Fine: we know the exact type to convert to 
Action a =() => Console.WriteLine("Yay"); 

// Doesn't work: EventHandler isn't parameterless; we've specified 0 parameters 
EventHandler e1 =() => Console.WriteLine("Bang"); 
EventHandler e2 = delegate() { Console.WriteLine("Bang again"); }; 

// Works: we don't care about parameter lists 
EventHandler e = delegate { Console.WriteLine("Lambdas can't do this"); }; 
+4

Và tôi nghĩ tôi hiểu đại biểu và lambdas. Tôi thật ngu ngốc. – recursive

+0

Các nội dung hay ho hơn bao giờ hết, +1 cho "... là tính năng duy nhất mà chúng có biểu thức lambda không." – Ani

+1

@recursive, nếu bạn quan tâm để tìm hiểu thêm, hãy đọc trên cây biểu đạt. Điều thú vị về các biểu thức lambda là chúng thực sự là _expressions_, với một mô hình mô tả phong phú cho những gì được thể hiện, và không chỉ đơn thuần là một cú pháp cú pháp để truyền logic tới tham số ủy nhiệm. Đây là những gì cho phép phép thuật như LINQ to SQL xảy ra. http://msdn.microsoft.com/en-us/library/bb397951.aspx –

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