Perché le classi di raccolte in C # (come ArrayList) ereditano da più interfacce se una di queste interfacce eredita dal rimanente?
-
06-07-2019 - |
Domanda
Quando premo f12 sulla parola chiave ArrayList per passare ai metadati generati da vs2008, ho scoperto che la dichiarazione di classe generata è la seguente
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
So che IList eredita già da ICollection e IEnumerable, quindi perché ArrayList eredita in modo ridondante da queste interfacce?
Soluzione
OK, ho fatto qualche ricerca. Se si crea la seguente gerarchia:
public interface One
{
void DoIt();
}
public interface Two : One
{
void DoItMore();
}
public class Magic : Two
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
E compilarlo, quindi fare riferimento alla DLL in una soluzione diversa, digitare Magic e premere F12, si otterrà il seguente:
public class Magic : Two, One
{
public Magic();
public void DoIt();
public void DoItMore();
}
Vedrai che la gerarchia dell'interfaccia è appiattita o che il compilatore sta aggiungendo le interfacce? Se usi il riflettore otterrai anche gli stessi risultati.
Aggiornamento: se apri la DLL in ILDASM, la vedrai dire:
implementa ... Due
implementa ... Uno.
Altri suggerimenti
Le interfacce extra sono mostrate perché sono implicite da IList. Se si implementa IList, è necessario implementare anche ICollection e IEnumerable.
Sto solo indovinando, ma penso che in realtà implementa solo IList nel codice, ma la documentazione mostra anche il resto delle interfacce per renderlo esplicito al programmatore che usa la classe.
Da MSDN ....
Se una classe implementa due interfacce che contengono un membro con lo stesso firma, quindi implementandola membro della classe causerà entrambi interfacce per usare quel membro come loro implementazione.
Viene anche utilizzata l'implementazione esplicita per risolvere i casi in cui due interfacce ciascuno dichiara membri diversi del stesso nome come proprietà e a Metodo:
Non accettarlo come risposta.
Sto ripetendo ciò che workmad3 ha detto sopra.
Implementandolo in ArrayList, diventa facile per uno sapere - quali interfacce ArrayList implementa piuttosto che andare su IList per scoprire che implementa ICollection & amp; IEnumerable.
Questo evita la necessità di tornare indietro & amp; avanti la catena ereditaria.
EDIT: a livello base, un'interfaccia che implementa un'altra interfaccia non può fornire l'implementazione. La classe derivata (da IList) implementa quindi indirettamente ICollection & amp; Anche IEnumerable. Quindi, anche se scrivi la tua classe implementando IList (e non aggiungi ICollection, IEnumerable nella dichiarazione) - vedrai che dovrà fornire l'implementazione per ICollection & amp; IEnumerable.
E il ragionamento di workmad3 ha senso.
La mia ipotesi sarebbe che il CLR non supporti un'interfaccia che eredita da un'altra interfaccia.
C # tuttavia supporta questo costrutto ma deve 'appiattire' l'albero delle eredità per essere conforme a CLR.
[Modifica]
Dopo aver ricevuto la consulenza dal basso, impostare rapidamente un progetto VB.Net:
Public Interface IOne
Sub DoIt()
End Interface
Public Interface ITwo
Inherits IOne
Sub DoIt2()
End Interface
Public Class Class1
Implements ITwo
Public Sub DoIt() Implements IOne.DoIt
Throw New NotImplementedException()
End Sub
Public Sub DoIt2() Implements ITwo.DoIt2
Throw New NotImplementedException()
End Sub
End Class
Risultati della compilazione nel seguente (C #):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
Questo mostra che VB.Net non NON appiattisce la gerarchia dell'interfaccia rispetto a C #. Non ho idea del perché questo sarebbe.