2011-09-22 40 views
12

Tôi hơi bối rối về cách thức hoạt động của các phương thức tiện ích mở rộng.C# Phương thức mở rộng ưu tiên

Nếu tôi đọc chính xác http://msdn.microsoft.com/en-us/library/bb383977.aspx và điều này If an extension method has the same signature as a method in the sealed class, what is the call precedence?.

Sau đó, điều sau đây sẽ ghi ra "Sơ thẩm", nhưng thay vào đó nó viết "Phương pháp mở rộng".

interface IFoo 
{ 
} 

class Foo : IFoo 
{ 
    public void Say() 
    { 
     Console.WriteLine("Instance"); 
    } 
} 

static class FooExts 
{ 
    public static void Say(this IFoo foo) 
    { 
     Console.WriteLine("Extension method"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IFoo foo = new Foo(); 
     foo.Say(); 
    } 
} 

Đánh giá cao sự trợ giúp trong việc làm rõ hành vi.

+0

Bạn có chắc chắn ghi đè phương pháp tích hợp với phương thức mở rộng không? – kenny

+0

Trong nháy mắt thứ hai hoặc biên dịch nó, giao diện không có Say(), vì vậy những gì bạn đã gọi phương thức mở rộng. Với Save() trong giao diện trình biên dịch phàn nàn với 'C: \ projects \ _play \ ExtensionMethods \ Program.cs (2,1): lỗi CS0116: Không gian tên không thể chứa trực tiếp các thành viên như trường hoặc phương thức' – kenny

Trả lời

14

Sự khác biệt lớn ở đây là bạn đã xác định phương thức tiện ích cho giao diện IFoo và biến số foo của bạn thuộc loại IFoo.

Nếu mã của bạn là như thế này:

Foo foo = new Foo(); 
foo.Say() 

Phương pháp Foo.Say() sẽ được thực hiện, không phải là phương pháp khuyến nông.

Tôi ước tôi có thể cung cấp cho bạn giải thích kỹ lưỡng về lý do tại sao điều này là nhưng tôi chỉ có thể bao gồm cơ chế cơ bản. Khi biến của bạn là loại IFoo và không phải là Foo, khi trình biên dịch cố gắng xác định phương thức nào có sẵn, nó đã xem qua bất kỳ phương thức không giao diện nào của lớp Foo (vì nó nên). Tuy nhiên, phương thức mở rộng Say() đã có sẵn, do đó, nó đã gọi ra phương thức này.

+2

Để thêm vào điều này , khi bạn sử dụng 'IFoo foo = ..', kiểu foo là' IFoo' mặc dù nó trỏ đến một thể hiện của 'Foo'. 'Foo foo ...' gọi phương thức trên đối tượng, 'IFoo foo' làm cho' Say() 'mở rộng thành' FooExts.Say (foo) '. Chạy 'ildasm' và thả .exe vào nó để xem IL. –

+0

Cảm ơn Jim mẹo tốt. – Dax70

4

Trong số Main, foo của bạn được khai báo là IFoo. Khi trình biên dịch tìm kiếm một phương thức Say, trình tìm kiếm chỉ tìm thấy phương thức mở rộng. Điều này là do phương pháp thể hiện được khai báo trong Foo, không phải trong IFoo. Trình biên dịch không biết rằng biến số foo xảy ra để chứa một phiên bản của Foo; nó chỉ nhìn vào kiểu biến được khai báo.

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