¿Por qué las clases de colecciones en C # (como ArrayList) heredan de varias interfaces si una de estas interfaces hereda de las restantes?
-
06-07-2019 - |
Pregunta
Cuando presiono f12 en la palabra clave ArrayList para ir a los metadatos generados a partir de vs2008, descubrí que la declaración de clase generada es la siguiente
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
Sé que IList ya hereda de ICollection e IEnumerable, entonces, ¿por qué ArrayList hereda de forma redundante de estas interfaces?
Solución
Bien, he investigado un poco. Si crea la siguiente jerarquía:
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();
}
}
Y compílelo, luego haga referencia a la DLL en una solución diferente, escriba Magic y presione F12, obtendrá lo siguiente:
public class Magic : Two, One
{
public Magic();
public void DoIt();
public void DoItMore();
}
¿Verá que la jerarquía de la interfaz está aplanada o que el compilador agrega las interfaces? Si usa el reflector, obtendrá los mismos resultados también.
Actualización: si abre la DLL en ILDASM, verá que dice:
implementa ... Dos
implementa ... Uno.
Otros consejos
Las interfaces adicionales se muestran porque están implicadas por IList. Si implementa IList, también debe implementar ICollection e IEnumerable.
Solo estoy adivinando, pero creo que en realidad solo implementa IList en el código, pero la documentación también muestra el resto de las interfaces para hacerlo explícito al programador que usa la clase.
De MSDN ....
Si una clase implementa dos interfaces que contienen un miembro con el mismo firma, luego implementando eso miembro de la clase causará tanto interfaces para usar ese miembro como su implementación.
La implementación explícita también se usa para resolver casos donde dos interfaces cada uno declara diferentes miembros de la mismo nombre como una propiedad y un método:
No acepte esto como respuesta.
Estoy repitiendo lo que workmad3 dijo anteriormente.
Al implementarlo en ArrayList, resulta fácil para uno saber qué interfaces implementa ArrayList en lugar de ir a IList para encontrar que implementa ICollection & amp; IEnumerable.
Eso evita la necesidad de retroceder & amp; adelante la cadena de herencia.
EDITAR: en el nivel básico, una interfaz que implementa otra interfaz no puede proporcionar la implementación. La clase derivada (de IList) implementa indirectamente ICollection & amp; IEnumerable también. Entonces, incluso si escribe su propia clase implementando IList (y no agrega ICollection, IEnumerable en la declaración), verá que tendrá que proporcionar la implementación para ICollection & amp; IEnumerable.
Y el razonamiento de workmad3 tiene sentido.
Supongo que CLR no admite una interfaz que herede de otra interfaz.
C #, sin embargo, admite esta construcción, pero tiene que 'aplanar' el árbol de herencia para que sea compatible con CLR.
[Editar]
Después de seguir los consejos de abajo, configure rápidamente un proyecto 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
Compilación de resultados en el siguiente (C #):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
Esto muestra que VB.Net NO aplana la jerarquía de la interfaz en lugar de C #. No tengo idea de por qué esto sería.