2009-06-21 8 views
31

Cuando presiono F12 en la palabra clave ArrayList para ir con los metadatos generados a partir de VS2008, he encontrado que la declaración de clase generado como sigue¿Por qué las clases de colecciones en C# (como ArrayList) heredan de múltiples interfaces si una de estas interfaces hereda del resto?

public class ArrayList : IList, ICollection, IEnumerable, ICloneable 

sé que el IList ya se hereda de ICollection y IEnumerable, así que ¿por qué ArrayList heredar de forma redundante de estas interfaces?

+2

+1 Esa es una muy buena pregunta. – AnthonyWJones

+0

Estoy de acuerdo. En el reflector ArrayList se define como clase pública ArrayList: IList, ICollection, IEnumerable, ICloneable – RichardOD

+0

Investigué un poco y agregué una respuesta con un ejemplo de código – RichardOD

Respuesta

14

OK, he hecho un poco de investigación. 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 compilarlo, a continuación, hacer referencia a la DLL en una solución diferente, el tipo de magia y Pulse F12, se obtendrán los siguientes:

public class Magic : Two, One 
    { 
     public Magic(); 

     public void DoIt(); 
     public void DoItMore(); 
    } 

Usted verá que la jerarquía de la interfaz es aplanada, o el compilador está agregando las interfaces en? Si usas un reflector obtienes los mismos resultados también.

Actualización: Si abre el archivo DLL en ILDASM, verá que dice:

implementos ... Dos

implementos ... Uno.

+0

está bien, pero por qué se menciona en la documentación –

+0

Supongo que porque es bastante útil saber eso. No todo el mundo sabe que IList hereda de ICollection e IEnumerable (o reemplaza esta instancia por otra jerarquía). – RichardOD

3

Las interfaces adicionales se muestran porque están implícitas en IList. Si implementa IList, también debe implementar ICollection e IEnumerable.

+0

bien, esto significa que se genera a partir de vs y no es la declaración real de ArrayList? –

+0

Sí. Si usa Reflector para ver los tipos de base, verá que solo implementa explícitamente Ilist e ICloneable. Ese también es el caso en el código fuente público de Rotor de Microsoft: http://www.123aspx.com/Rotor/RotorSrc.aspx?rot=39810 – Zr40

+1

Supongo que VS podría aplanar la implementación del método. Es decir, dado que IList implementa ICollection, ArrayList proporciona la implementación de métodos ICollection. – shahkalpesh

2

Solo estoy adivinando, pero creo que en realidad solo implementa IList en el código, pero la documentación muestra el resto de las interfaces también para hacerlo explícito al programador que usa la clase.

+3

Incluso si implementa explícitamente todas ellas, la explicidad de las interfaces es buena como usted Luego, puede ver todo lo que necesita implementar con solo mirar esas interfaces, en lugar de explorar las interfaces y sus bases, etc. – workmad3

+0

Puedo ver su punto, pero soy escéptico en cuanto a si esto es algo bueno o no. Supongo que no está de más ser un poco redundante, pero no podría verme a mí mismo codificando algo de esta manera, lo que aún me lleva a preguntar: ¿dónde ha documentado MS sus intenciones para hacer esto? – mkelley33

1

De MSDN ....

Si una clase implementa dos interfaces que contienen un miembro con el mismo firma, a continuación, la aplicación de esa miembro de la clase hará que ambos interfaces para usar ese miembro como su implementación .

aplicación explícita también se utiliza para resolver los casos en que dos interfaces cada declaran diferentes miembros de la mismo nombre como una propiedad y un método :

+0

Mi pregunta es ¿por qué ArrayList hereda de ICollection e IEnumerable mientras IList herede de ambos? –

0

No acepte esto como respuesta.

Estoy repitiendo lo que workmad3 dijo anteriormente.

Al implementarlo en ArrayList, es fácil de saber: qué interfaces ArrayList implementa en lugar de ir a IList para encontrar que implementa ICollection & IEnumerable.

Eso evita la necesidad de volver atrás & 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 & IEnumerable también. Entonces, incluso si escribe su propia clase implementando IList (y no añade ICollection, IEnumerable en la declaración), verá que deberá proporcionar la implementación para ICollection & IEnumerable.

Y el razonamiento de workmad3 tiene sentido.

0

Supongo que el CLR no admite una interfaz que hereda de otra interfaz.

C# sin embargo, admite esta construcción, pero tiene que "aplanar" el árbol de herencia para que cumpla con CLR.

[Editar]

Después de tomar el asesoramiento de configuración a continuación 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 los resultados en el siguiente (C#):

public class Class1 : ITwo 
{ 
    public Class1(); 
    public void DoIt(); 
    public void DoIt2(); 
} 

Este espectáculo que VB.Net no hace NOT allanar la jerarquía de interfaz en lugar de C#. No tengo idea de por qué sería esto.

+0

-1: En lugar de adivinar tres semanas después, ¿por qué no probarlo en VB.NET y averiguarlo antes de responder? Seguramente no había apuro. –

+0

Excelente. He votado a favor –

Cuestiones relacionadas