Pourquoi les classes de collections en C # (comme ArrayList) héritent-elles de plusieurs interfaces si l'une de ces interfaces hérite des autres?
-
06-07-2019 - |
Question
Lorsque j'appuie sur f12 sur le mot clé ArrayList pour accéder aux métadonnées générées à partir de vs2008, j'ai constaté que la déclaration de classe générée était la suivante
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
Je sais que IList hérite déjà de ICollection et IEnumerable, alors pourquoi ArrayList hérite-t-il de manière redondante de ces interfaces?
La solution
OK, j'ai fait des recherches. Si vous créez la hiérarchie suivante:
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();
}
}
Et compilez-le, puis référencez la DLL dans une solution différente, tapez Magic et appuyez sur F12, vous obtiendrez les éléments suivants:
public class Magic : Two, One
{
public Magic();
public void DoIt();
public void DoItMore();
}
Vous verrez que la hiérarchie des interfaces est aplatie ou que le compilateur ajoute les interfaces? Si vous utilisez un réflecteur, vous obtenez également les mêmes résultats.
Mise à jour: si vous ouvrez la DLL dans ILDASM, vous la verrez ainsi:
implémente ... Deux
implémente ... Un.
Autres conseils
Les interfaces supplémentaires sont affichées car elles sont impliquées par IList. Si vous implémentez IList, vous devez également implémenter ICollection et IEnumerable.
Je ne fais que deviner, mais je pense qu'en réalité, il implémente seulement IList dans le code, mais la documentation montre également le reste des interfaces pour le rendre explicite au programmeur qui utilise la classe.
De MSDN ....
Si une classe implémente deux interfaces qui contiennent un membre avec le même signature, puis la mise en œuvre membre de la classe causera à la fois interfaces pour utiliser ce membre en tant que leur la mise en oeuvre.
L'implémentation explicite est également utilisée pour résoudre les cas où deux interfaces déclarent chacun des membres différents du même nom tel qu'une propriété et un méthode:
N'acceptez pas cela comme réponse.
Je répète ce que workmad3 a dit plus haut.
En l'implémentant dans ArrayList, il est facile de savoir - les interfaces implémentées par ArrayList plutôt que de rechercher IList pour savoir qu'il implémente ICollection & amp; IEnumerable.
Cela évite d'avoir à revenir en arrière & amp; vient la chaîne de l'héritage.
EDIT: Au niveau de base, une interface implémentant une autre interface ne peut pas fournir l’implémentation. La classe dérivée (de IList) implémente donc indirectement ICollection & amp; IEnumerable aussi. Ainsi, même si vous écrivez votre propre classe implémentant IList (et que vous n’ajoutez pas ICollection, IEnumerable dans la déclaration), vous verrez qu’elle devra fournir l’implémentation pour ICollection & amp; IEnumerable.
Et le raisonnement de workmad3 est logique.
Je pense que le CLR ne prend pas en charge une interface héritant d'une autre interface.
C # supporte cependant cette construction mais doit "aplatir" l'arbre d'héritage pour qu'il soit conforme au CLR.
[Modifier]
Après avoir pris conseil ci-dessous, configurez rapidement un projet 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
La compilation des résultats dans les éléments suivants (C #):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
Cela montre que VB.Net NOT n'aplatit pas la hiérarchie des interfaces, contrairement à C #. Je ne sais pas pourquoi cela se produirait.