2012-01-20 33 views
10

Tôi tự hỏi tại sao đầu ra của mã nhất định (thực hiện nó trong LinqPad)phương pháp Implicit chuyển đổi nhóm Gotcha

void Main() { 
    Compare1((Action)Main).Dump(); 
    Compare2(Main).Dump(); 
} 

bool Compare1(Delegate x) { 
    return x == (Action)Main; 
} 

bool Compare2(Action x) { 
    return x == Main; 
} 

luôn là:

False 
True 

tôi đã ngây thơ mong đợi nó được True trong cả hai trường hợp.

+1

Thay đổi 'Compare1' để sử dụng' return x == (Delegate) (Hành động) Main; 'làm cho nó trả về' true'. Không chắc chắn tại sao mặc dù. – Joey

+0

FYI: Tôi đã hỏi một câu hỏi tương đối ở đây: http: //stackoverflow.com/questions/8939350/implicit-method-group-conversion-gotcha-part-2 –

Trả lời

9

Đây là giao diện của nó khi được biên dịch sang IL và sau đó được dịch ngược về C#. Lưu ý rằng trong cả hai trường hợp có new Action(Main) - một đối tượng tham chiếu mới (delegate) với con trỏ đến phương thức thực được lưu trữ bên trong.

private static void Main() 
{ 
    Program.Compare1(new Action(Program.Main)).Dump(); 
    Program.Compare2(new Action(Program.Main)).Dump(); 
    Console.ReadLine(); 
} 

private static bool Compare1(Delegate x) 
{ 
    return x == new Action(Program.Main); 
} 

private static bool Compare2(Action x) 
{ 
    return x == new Action(Program.Main); 
} 

Nếu sau đó chúng ta hãy nhìn vào CIL, việc sử dụng cựu ceq (so sánh tham khảo) và những ứng dụng sau call bool [mscorlib]System.Delegate::op_Equality(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) để so sánh các đại biểu.

Lợi nhuận đầu tiên false vì các hành động gói đại biểu của bạn là hai đối tượng tham chiếu riêng biệt.

Lợi nhuận thứ hai true là toán tử bình đẳng được triển khai trên lớp Delegate so sánh mục tiêu thực tế bên trong trình bao bọc (hành động).

7

Các false kết quả có liên quan đến một thực tế là Compare1() phương pháp thực hiện so sánh tham khảo trên hai đối tượng khác nhau (compilator cho thấy cảnh báo tương ứng):

IL_0001: ldarg.0 
IL_0002: ldnull 
IL_0003: ldftn  instance void ConsoleApplication1.Test::Main() 
IL_0009: newobj  instance void [System.Core]System.Action::.ctor(object, 
                    native int) 
IL_000e: ceq <<reference comparison 

Bạn có thể tránh vấn đề bằng cách sử dụng đoạn mã sau:

bool Compare1(Delegate x) { 
    return x == (Delegate)((Action)Main); 
} 
Các vấn đề liên quan