2010-09-08 41 views
31

Tôi chạy vào một trường hợp cạnh C# lạ và đang tìm kiếm một công việc tốt xung quanh.Tại sao trình biên dịch C# chèn một giao diện thực hiện rõ ràng?

Có một lớp mà tôi không kiểm soát trông như thế này:

namespace OtherCompany 
{ 
    public class ClassIDoNotControl 
    { 
     public void SomeMethod(string argument) 
     { 
      Console.WriteLine((new StackFrame(1).GetMethod().Name)); 
     } 
    } 
} 

Tôi muốn kế thừa từ lớp này trong một lớp I làm kiểm soát. Ngoài ra, tôi muốn chỉ định một giao diện trên đó:

interface IInterfaceIDoControl 
{ 
    void SomeMethod(string argument); 
} 

class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl 
{ 
} 

Nếu tất cả các tập tin nằm trong cùng một hội đồng, mọi thứ hoạt động tốt:

namespace MyCompany 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      IInterfaceIDoControl i = new ClassIDoControl(); 
      i.SomeMethod("Hello World!"); // Prints "Main" 
     } 
    } 
} 

Nhưng, nếu tôi di chuyển "ClassIDoNotControl" vào một hội đồng khác, tôi không hiểu những gì tôi mong đợi. Thay vào đó, tôi thấy "MyCompany.IInterfaceIDoControl.SomeMethod" cho đầu ra ngụ ý một khung stack bổ sung.

Lý do là theo bao, các biên dịch C# đang thay đổi "ClassIDoControl" trông như thế này:

class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl 
{ 
    void IInterfaceIDoControl.SomeMethod(string argument) 
    { 
     base.SomeMethod(argument); 
    } 
} 

Có cách nào để tránh trình biên dịch tạo này thêm lớp về mình với giao diện thực hiện một cách rõ ràng ?

+2

Tôi ngạc nhiên khi nó hoạt động trong trường hợp đầu tiên. – Grzenio

Trả lời

43

Câu trả lời ngắn: CLR yêu cầu tất cả các phương pháp triển khai phương thức giao diện phải là ảo (Ecma 335 Partition II Mục 12.1).

Long trả lời:

  • Nếu phương pháp trong lớp cơ sở là đã ảo, sau đó không có gì thêm là cần thiết: các phương pháp giao diện có thể được liên kết với nó.

  • Nếu phương pháp trong lớp cơ sở là không ảo, nhưng trong cùng một assembly, trình biên dịch lén lút thực làm cho nó ảo và thức. Reflector xác nhận điều này. (“cuối cùng” là thuật ngữ CLR cho “kín” trong C#.)

  • Nếu phương pháp trong lớp cơ sở không phải là ảo và trong lắp ráp khác, sau đó rõ ràng là trình biên dịch có thể không làm điều này vì nó không thể sửa đổi assembly đã được biên dịch. Do đó, tùy chọn duy nhất ở đây là chèn phương thức chuyển hướng thực hiện phương thức giao diện. Giống như tất cả các phương pháp triển khai phương thức giao diện, nó cũng được đánh dấu ảo và cuối cùng.

Vì vậy, câu trả lời cho câu hỏi cuối cùng của bạn, “Có cách nào để tránh điều này không?”, Rất tiếc là không.

+0

Ah ha! Tôi đã không nhận thấy rằng sự thay đổi tinh tế trong việc tháo gỡ C# trong Reflector, nhưng bạn nói đúng là nó xuất hiện trong quan điểm IL với thủ thuật "ảo cuối cùng" đó. Tôi đã học được một cái gì đó mới ngày hôm nay. –

+0

[Tôi cũng vậy ☺] (http://meta.stackexchange.com/questions/700/) – Timwi

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