2013-06-20 26 views
12

Trong C# tất cả các loại đại biểu không tương thích với nhau, ngay cả khi chúng có chữ ký giống nhau. Ví dụ:Tại sao tất cả các loại đại biểu không tương thích với nhau?

delegate void D1(); 
delegate void D2(); 

D1 d1 = MethodGroup; 
D2 d2 = d1;       // compile time error 
D2 d2 = new D2 (d1);     // you need to do this instead 

Lý do đằng sau quyết định thiết kế ngôn ngữ và hành vi này là gì.

+2

Tôi không thể cung cấp cho bạn lý do, nhưng đại biểu là một tính năng ngôn ngữ gốc. Kể từ đó, họ đã thêm các phương thức lambda, [Actions] (http://msdn.microsoft.com/en-us/library/system.action.aspx) và [Funcs] (http://msdn.microsoft.com/ en-us/library/bb534960.aspx) không bị cùng một vấn đề. – Brandon

+0

@Brandon Cái gì? Các lambdas được chuyển đổi thành các delegate (hoặc các cây biểu thức) và 'Action' và 'Func' * chỉ là các loại đại biểu, vì vậy chúng tuân theo chính xác các quy tắc tương tự. – svick

+0

Yêu cầu ủy quyền cũng được kiểm tra trong thời gian chạy. Điều đó đã được tối ưu hóa, một loại tối ưu hóa quan trọng, chỉ hỗ trợ nhận dạng loại nghiêm ngặt. Nhanh thật. –

Trả lời

23

In C# all delegate types are incompatible with one another, even if they have the same signature. What is the reasoning behind this behaviour and language design decision?

Trước hết, tôi nghĩ rằng nó là công bằng để nói rằng rất nhiều các nhà thiết kế thời gian chạy và ngôn ngữ hối tiếc quyết định này. Kết cấu gõ trên các đại biểu - có nghĩa là, phù hợp với chữ ký - là một tính năng thường xuyên yêu cầu và nó chỉ có vẻ lạ rằng Func<int, bool>Predicate<int> không thể được tự do giao cho nhau.

Lý do đằng sau quyết định khi tôi hiểu - và tôi đẩy nhanh thêm rằng quyết định này được thực hiện khoảng sáu năm trước khi tôi bắt đầu nhóm C# - đó là kỳ vọng rằng sẽ có các loại đại biểu với ngữ nghĩa. Bạn muốn đây là một lỗi type:

AnyFunction<int, int> af = x=> { Console.WriteLine(x); return x + y; }; 
PureFunction<int, int> pf = af; 

Một chức năng "thuần túy" là một chức năng trong đó sản xuất và tiêu thụ không có tác dụng phụ, tiêu thụ không có thông tin bên ngoài của đối số của nó, và trả về một giá trị nhất quán khi đưa các đối số tương tự . Rõ ràng af không thành công ít nhất hai trong số đó và do đó không được chuyển nhượng thành pf dưới dạng chuyển đổi ẩn.

Nhưng các loại đại biểu mang tính ngữ nghĩa không bao giờ xảy ra, do đó, hiện tại nó hơi bị lỗi.

+1

Tôi sẽ phải nhớ thuật ngữ đó, '* misfeature *'. –

+1

Tôi sẽ nhớ với sự thích thú trong thời gian ngắn tôi đã có câu trả lời với nhiều phiếu bầu hơn Eric Lippert. –

15

Về cơ bản vì trình biên dịch tạo hai lớp cho bạn. Lý do mà bạn không thể làm:

class A {} 
class B {} 

void Main() 
{ 
    A a = new A(); 
    B b = a; 
} 

Ví dụ, đoạn mã sau

void Main() {} 

delegate void D(); 
class C {} 

Mã IL là:

D.Invoke: 

D.BeginInvoke: 

D.EndInvoke: 

D..ctor: 

C..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret   
2

đại biểu là gì, nhưng chỉ là một kiểu. Chúng không tương thích với cùng một lý do class A {}class B {} sẽ không tương thích.

delegate void D1(); 

xấp xỉ sẽ biên dịch một cái gì đó như:

class D1 : MulticastDelegate { .... } 
Các vấn đề liên quan