2011-01-30 45 views
11

Có kế thừa một quan hệ chuyển tiếp trong C# không?C#: Thừa kế thừa kế

Tôi hỏi vì tôi không thể hiểu tại sao IList<T> thực hiện ICollection<T>IEnumerable<T> như ICollection<T> đã thực hiện IEnumerable<T>

Cảm ơn để làm rõ điều này cho tôi.

+0

bạn có thể tìm thấy một số câu trả lời trong [câu hỏi] tương tự này [1] [1]: http://stackoverflow.com/questions/1164757/why-arraylist-implement-ilist-icollection-ienumerable – DesignFirst

+0

http://stackoverflow.com/questions/4754923/a-question-about-interface-inheritance-in-net/4755044#4755044 – explorer

+0

Đây cũng là bản sao của http://stackoverflow.com/questions/4817369/why -does-does-realy-list-implements-all-of-that-interfaces-not-just-ilistt/4818566 # 4818566 –

Trả lời

4

AFAIK, nó không thực sự quan trọng cho dù bạn tuyên bố IList<T> như:

public interface IList<T> : ICollection<T>, IEnumerable<T> { ... } 

hoặc đơn giản là:

public interface IList<T> : ICollection<T> { ... } 

Bất kỳ lớp mà muốn thực hiện IList<T> sẽ phải thực hiện tất cả các của các giao diện này, tức là các giao diện được kế thừa.

Rõ ràng, nếu bạn triển khai giao diện này mà không triển khai phương thức GetEnumerator của giao diện IEnumerable/IEnumerable<T>, bạn sẽ gặp lỗi trình biên dịch; "bằng chứng" này bằng cách trình diễn là đủ để cho bạn biết rằng "giao diện thừa kế" là transitive, thực sự.


Sidenote 1. Trên một mặt lưu ý (và hơi lạc đề), hãy xem xét rằng bạn cũng có thể làm như sau:

class Base 
{ 
    public void Foo() { ... } 
} 

interface IFoo 
{ 
    void Foo(); 
} 

class Derived : Base, IFoo 
{ } 

Derived không thực sự thực hiện IFoo; lớp cơ sở Base cung cấp phương thức Foo, nhưng không thực hiện rõ ràng chính mình IFoo.

Điều này biên dịch tốt, dường như bởi vì tất cả các phương pháp được yêu cầu bởi các giao diện là có. (Tôi sẽ để nó ở đó và rời khỏi cuộc nói chuyện kỹ thuật chính xác sang một bên.)

Lý do tại sao tôi đề cập đến hiện tượng dường như không liên quan này là tôi thích suy nghĩ về giao diện theo cách này: Bạn cần thực hiện tất cả các phương thức được yêu cầu bởi các giao diện được chỉ định trong khai báo lớp. Vì vậy, khi tôi nhìn thấy

interface ICollection<T> : IEnumerable<T> { ... } 

thay vì nói, "ICollection<T> thừa hưởng IEnumerable<T>", tôi có thể nói với bản thân mình, "ICollection<T> đòi hỏi của mọi tầng lớp triển khai rằng họ thực hiện IEnumerable<T>, cũng có."


Sidenote 2. Để kết luận câu trả lời này với một giai thoại có phần liên quan khác (Tôi hứa nó sẽ là câu chuyện cuối cùng):

Một thời gian trước, tôi đã xem video Inside .NET Rx and IObservable/IObserver in the BCL trên Kênh 9. Như bạn có thể, hai giao diện mới sắp tới từ Rx, đã được giới thiệu vào BCL với .NET 4. Một điều đặc biệt là khi bạn đăng ký một người quan sát đến một quan sát qua observable.Subscribe(observer), tất cả những gì bạn nhận được là một số ẩn danh IDisposable. Tại sao?

Khi người nói chuyện giải thích trong video đó, họ có thể trao IDisposable tên mô tả hơn (chẳng hạn như ISubscription), thông qua một tên kiểu "bí danh" được định nghĩa như sau:

interface ISubscription : IDisposable {} 

Tuy nhiên, họ cuối cùng quyết định chống lại điều này. Họ nhận thấy rằng khi một phương thức ISubscription được trả về từ phương thức Subscribe, sẽ không còn rõ ràng rằng giá trị trả lại cần phải là Dipose d.

Vì vậy, đó là một khía cạnh hơi có vấn đề khác của "giao tiếp thừa kế" mà người ta nên ghi nhớ.

8

Tất cả đều liên quan đến nhau. Có lẽ công cụ mà bạn sử dụng để xem xét hệ thống phân cấp thừa kế có một cách nhất định để hiển thị nó. Không có cách nào để unimplement một giao diện mặc dù bạn có thể thực hiện nó một cách rõ ràng và do đó ẩn nó khỏi intellisense.

Là tác giả của IList, bạn có thể tự do lựa chọn để lấy được từ ICollection chỉ hoặc từ ICollection và IEnumerable. IEnumerable sẽ là dự phòng trong trường hợp này và được gắn cờ bằng resharper.

+0

Xin lỗi vì đã làm gián đoạn, nhưng "và được gắn cờ bằng cách chia sẻ lại" khiến tôi chú ý. Resharper chỉ là một công cụ, không phải là một guru lập trình. Nó cũng cờ nhiều thứ khác mà nếu thay đổi gây rắc rối sau này. (ví dụ: cờ tuyên bố rõ ràng được thay đổi thành ẩn (var)) – kubal5003

+0

Có. Tôi chỉ có nghĩa là câu đó để cung cấp bằng chứng xã hội rằng người lập trình chia sẻ lại đồng ý với tôi. – usr