2012-08-24 51 views
11

Tôi có lớp cơ sở Aphương pháp Tại sao quá tải có ưu tiên thấp hơn so với phương pháp dụ

public class A 
{ 
    public virtual void Method(A parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
    public virtual void Method(B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

Inhereted B

public class B : A 
{ 
    public virtual void Method(object parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 

    public override void Method(A parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 

    public override void Method(B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

lớp tĩnh S với phương pháp khuyến nông

public static class S 
{ 
    public static void Method(this B instance, B parameter) 
    { 
     Console.WriteLine(MethodBase.GetCurrentMethod()); 
    } 
} 

Ví dụ chúng ta tạo ra ví dụ của loại B và gọi Method trên đó, chúng tôi hy vọng rằng nó sẽ là public override void Method(B parameter) kết quả thực tế là public virtual void Method(object parameter).

var b = new B(); 
b.Method(new B()); // B.Method (Object parameter) Why??? 

Tại sao trình biên dịch không chọn phương thức phù hợp hơn ??? UPD Và tại sao nó không phải là phương pháp mở rộng?

+3

'B' không được lồng ghép nhưng được kế thừa. –

+0

@Henk Holterman nhờ phương thức mở rộng – user854301

+0

không được gọi nếu đối tượng có cùng một phương thức. điều này là để tránh phá vỡ mã cũ, nơi kỳ vọng là gọi phương thức cũ và không phải là phần mở rộng mới. – Ankush

Trả lời

10

Tại sao trình biên dịch không chọn phương thức phù hợp hơn?

Bởi vì đó là theo các quy tắc của đặc tả ngôn ngữ, nơi bất kỳ phương pháp ứng cử viên ban đầu tuyên bố trong một lớp cơ sở (hơn nếu họ đang ghi đè trong một lớp học có nguồn gốc) được bỏ qua khi tìm kiếm một phương pháp ứng cử viên, trừ trường hợp lớp dẫn xuất không có bất kỳ phương pháp áp dụng nào, tại thời điểm đó tìm kiếm di chuyển lên đến lớp cơ sở, v.v.

Đây là designed to avoid the "brittle base class" problem, nhưng tôi thấy khó nuốt khi đối mặt với phương pháp bị ghi đè trong nguồn gốc lớp học.

Các bit có liên quan của các đặc điểm kỹ thuật C# 4 là 7.4, kết thúc với điều này:

Đối tra cứu viên trong các loại khác hơn là thông số loại hình và giao diện, và tra cứu viên trong giao diện đó là đúng đơn thừa kế (mỗi giao diện trong chuỗi thừa kế có chính xác không hoặc một giao diện cơ sở trực tiếp), hiệu quả của các quy tắc tra cứu đơn giản là các thành viên có nguồn gốc ẩn các thành viên cơ sở có cùng tên hoặc chữ ký.

EDIT: Về phương pháp khuyến nông ...

Và tại sao nó không phải là phương pháp mở rộng?

Từ phần 7.6.5.2 của spec:

Trong một gọi phương pháp (§7.5.5.1) của một trong các hình thức

expr . identifier () 
expr . identifier (args) 
expr . identifier <typeargs> () 
expr . identifier <typeargs> (args) 

nếu chế biến bình thường của invocation không tìm thấy phương pháp áp dụng nào, một nỗ lực được thực hiện để xử lý cấu trúc dưới dạng lời gọi phương thức mở rộng

Vì vậy, phương pháp mở rộng là chỉ có được sử dụng làm phương sách cuối cùng, về cơ bản.

+0

Tôi nghĩ câu hỏi là tại sao mã gọi phương thức kế thừa, chứ không phải là phương pháp mở rộng, nhưng khó mà nói được? – podiluska

+0

@podiluska: Tôi nghĩ rằng phương pháp mở rộng là một cá trích đỏ. OP dường như không mong đợi nó được gọi là ... –

+0

Nó cũng thú vị lý do tại sao phương pháp mở rộng không được gọi là quá. – user854301

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