2010-02-18 30 views
14

Tôi có thể gán phương thức M cho đối tượng d với loại tham số ít cụ thể hơn, nhưng khi tôi muốn gán một phương thức ẩn danh với cùng chữ ký theo phương thức M đến d, tôi gặp lỗi.Không thể gán cho ủy quyền một phương thức ẩn danh có kiểu tham số ít cụ thể

Tại sao lại như vậy?

class derivedEventArgs : EventArgs { } 

delegate void newDelegate(object o, derivedEventArgs e); 

static void Main(string[] args) 
{ 
    newDelegate d = M; // ok 
       d = (object o, EventArgs e) => { }; // error 
} 

public static void M(object o, EventArgs e) { } 
+2

Bạn chắc chắn có một số quy ước đặt tên thú vị đang diễn ra ở đó ... –

Trả lời

15

Tất nhiên là Jared đúng là thiết kế này.

Lý do cho thiết kế đó là trong trường hợp chuyển đổi phương pháp contravariant, bạn có thể có một phương thức mà bạn không viết và gán nó cho biến đại biểu mà bạn không viết. Bạn không kiểm soát các loại. Vì vậy, chúng tôi đi một chút dễ dàng vào bạn và để cho các thông số phù hợp contravariantly và các loại trả về phù hợp covariantly.

Trong chuyển đổi lambda-to-delegate, bạn làm kiểm soát điều đang được chỉ định. Không có gì là dừng lại bạn làm cho nó khớp chính xác trong các loại thông số và do đó chúng tôi yêu cầu bạn. Không có sự giả mạo nào được phép ở đây.

+0

Câu trả lời tuyệt vời.Cảm ơn cả hai đã giúp tôi – AspOnMyNet

16

Điều này được đề cập trong phần 6.5 của đặc tả ngôn ngữ C#. Nếu bạn nhập một cách rõ ràng các tham số của một hàm ẩn danh, chúng phải khớp với cả hai loại và các công cụ sửa đổi để có chữ ký tương thích.

Cụ thể, một loại đại biểu D là tương thích với một chức năng ẩn danh F cung cấp

...

Nếu F có một danh sách tham số gõ một cách rõ ràng, mỗi tham số trong D có cùng loại và bổ làm thông số tương ứng trong F.

+1

+1 câu trả lời rất nhanh. –

2

Khi bạn có câu trả lời, tôi sẽ cung cấp cách giải quyết nếu đây là yêu cầu. Này, tất cả các bạn đã là một đại biểu của chữ ký (object, EventArgs) trong trường hợp bạn muốn chuyển nó sang loại newDelegate của bạn, bạn có thể làm:

SomeDelegate p = (object o, EventArgs e) => { }; //comes from somewhere 
NewDelegate d = (o, e) => p(o, e); //can rewrite like this 

Cách khác với Generics và (Contra) Tính năng sai của đại biểu chung chung, bạn có thể làm điều đó với một loại đại biểu:

delegate void NewDelegate<in T>(object o, T e) where T : EventArgs; 

//then 
NewDelegate<EventArgs> p = (object o, EventArgs e) => { }; //comes from somewhere 
NewDelegate<DerivedEventArgs> d = p; //straightforward assignable - contravariance 
Các vấn đề liên quan