2011-01-30 3 views
11

Ereditarietà una relazione transitiva in C#?C#: Transitive Eredità

sto chiedendo perché non riesco a capire perché IList<T> implementa ICollection<T> e IEnumerable<T> come ICollection<T> implementa già IEnumerable<T>

Grazie per chiarire questo per me.

+0

si possono trovare alcune risposte in questo simile [domanda] [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

Questo è anche un duplicato di http://stackoverflow.com/questions/4817369/why -does-does-realy-list-implements-all-of-that-interfaces-not-just-ilistt/4818566 # 4818566 –

risposta

4

per quanto ne so, non ha veramente importa se dichiarato IList<T> come:

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

o semplicemente come:

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

Ogni classe che vuole implementare IList<T> dovrà implementare tutto di queste interfacce, cioè anche quelle ereditate.

Ovviamente, se avete implementato questa interfaccia senza implementare i metodi GetEnumerator delle interfacce IEnumerable/IEnumerable<T>, otterreste un errore del compilatore; questa "dimostrazione" per dimostrazione dovrebbe essere sufficiente a dirti che "l'ereditarietà dell'interfaccia" è transitoria, anzi.


Sidenote 1. Su un lato nota (e un po 'off-topic), considera che si può anche effettuare le seguenti operazioni:

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

interface IFoo 
{ 
    void Foo(); 
} 

class Derived : Base, IFoo 
{ } 

Derived in realtà non implementare IFoo; la sua classe base Base fornisce il metodo Foo, ma non implementa esplicitamente lo IFoo stesso.

Questo si compila bene, apparentemente perché ci sono tutti i metodi richiesti dalle interfacce. (Lascerò a questo e per il momento lascerò da parte i discorsi tecnici esatti.)

Il motivo per cui sto menzionando questo fenomeno apparentemente non correlato è che mi piace pensare all'ereditarietà dell'interfaccia in questo modo: è necessario implementare tutti i metodi richiesti dalle interfacce specificate nella dichiarazione della classe. Così, quando vedo

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

invece di dire, "ICollection<T> eredita IEnumerable<T>", potrei dire a me stesso, "ICollection<T> richiede di tutte le classi di attuazione che implementano IEnumerable<T>, anche."


Sidenote 2. Per concludere questa risposta con un altro aneddoto in qualche modo correlato (prometto che sarà l'ultimo):

Qualche tempo fa ho visto il video Inside .NET Rx and IObservable/IObserver in the BCL su Canale 9. Come potreste ora, quelle due nuove interfacce, in arrivo da Rx, sono stati introdotti nel BCL con .NET 4. Una cosa peculiare è che quando si iscrive un osservatore a un osservabile tramite observable.Subscribe(observer), tutto ciò che si ottiene è anonimo IDisposable. Perché?

Come i chiacchieroni spiegano in quel video, avrebbero potuto dato il IDisposable un nome più descrittivo (come ISubscription), tramite un nome di tipo "alias", definito come segue:

interface ISubscription : IDisposable {} 

Tuttavia, finalmente deciso contro questo. Hanno capito che una volta che un ISubscription viene restituito dal metodo Subscribe, non sarebbe più evidente che il valore restituito deve essere Dipose d.

Quindi questo è un altro lato leggermente problematico dell '"eredità di interfaccia" che è opportuno tenere a mente.

8

È transitivo sotto tutti gli aspetti. Probabilmente lo strumento che usi per esaminare la gerarchia dell'ereditarietà ha un certo modo di mostrarlo. Non c'è modo di non implementare un'interfaccia, sebbene tu possa implementarla esplicitamente e quindi nasconderla dall'intelligenza.

Come autore di IList è possibile scegliere liberamente di derivare da ICollection o da ICollection e IEnumerable. IEnumerable sarebbe ridondante in questo caso e contrassegnata dal resharper.

+0

Ci scusiamo per l'interruzione, ma "e contrassegnato da resharper" ha attirato la mia attenzione. Resharper è solo uno strumento, non un guru di programmazione. Contrassegna anche molte altre cose che, se cambiate, causano problemi in seguito. (ad esempio, contrassegna le dichiarazioni esplicite da modificare in implicito (var)) – kubal5003

+0

Sì. Intendevo solo quella frase per dare una prova sociale che la gente che programma il resharper era d'accordo con me. – usr