2012-09-17 9 views
24

Para un tiempo muy largo Tenía curiosidad acerca de lo siguiente:¿Cómo implementa Arrays IList <T> sin implementar la propiedad "Recuento" en C#?

int[] array = new int[1]; 
int iArrayLength = array.Length; //1 

Desde arrays implementan la interfaz IList, se permite lo siguiente:

int iArrayCount = ((IList<int>)array).Count; //still 1 

PERO:

int iArrayCount = array.Count; //Compile error. WHY? 
int iArrayLength = array.Length; //This is what we learned at school! 

El pregunta: ¿Cómo puede una matriz implementar IList<T> (especialmente la propiedad int Count { get; } desde IList<T>) sin permitir que se use en la clase base?

+0

Probablemente se podría simular este mismo sombreando la propiedad 'conde' de la clase base en su propia clase heredada, y hacerlo privado en su lugar. VB.NET tiene una palabra clave explícita 'Sombras' para esto, no está seguro acerca de C#, sin embargo. –

+0

Tu título es erróneo. Las matrices realmente implementan 'Count' desde [' ICollection'] (http://msdn.microsoft.com/en-us/library/system.collections.icollection.count.aspx): 'int ICollection.Count \t \t { \t \t \t obtener \t \t \t { \t \t \t \t vuelta esto.Longitud; \t \t \t} \t \t} '' pero –

+0

@TimSchmelter IList '' hereda de ICollection '; 'ICollection ' también tiene una propiedad 'Count', por lo que todos los tipos que implementen' IList 'también deben implementar' ICollection .Count'. Es cierto que la propiedad no está definida en 'IList ', pero la pregunta es razonable. – phoog

Respuesta

30

Esto se conoce como una implementación miembro de interfaz explícita. El miembro de interfaz no está expuesto como un miembro público del tipo, pero está disponible al convertir la referencia al tipo de interfaz.

Esto se puede hacer en C# como esto:

interface I 
{ 
    void M(); 
} 

class C : I 
{ 
    public int P { get; set; } 
    void I.M() { Console.WriteLine("M!"); } 
} 

continuación, puede utilizar estos tipos de esta manera:

C obj = new C(); 
obj.P = 3; 
((I)obj).M(); 

Pero esto no se compilará:

obj.M(); 

Como señala JeffN825, una razón para implementar la explicidad de los miembros de la interfaz es que no son compatibles con el tipo. Por ejemplo, Add arroja una excepción (relevant discussion). Otra razón para implementar una explicidad de miembro es que duplica a otro miembro público con un nombre diferente. Esa es la razón por la cual Count se implementa explícitamente; el miembro público correspondiente es Length. Finalmente, algunos miembros se implementan implícitamente, a saber, el indexador. Ambas líneas de trabajo (suponiendo arr es una matriz de int):

arr[0] = 8; 
((IList<int>)arr)[0] = 8; 
+0

"definición explícita de miembros de la interfaz" ¡una buena palabra clave para google! No lo sabía, ¡gracias! Es interesante que no tenga ningún modificador de acceso. Para que pueda usar sus interfaces internas en clases públicas sin tener que implementar todos los métodos/propiedades como públicos, ¡agradable! – Gerrit

+0

@Gerrit; en realidad, eso es incorrecto. Debe ser "implementación explícita del miembro de la interfaz". He corregido. – phoog

+0

@Gerrit Eric Lippert tiene una discusión interesante sobre el uso de interfaces internas en tipos públicos aquí: http://blogs.msdn.com/b/ericlippert/archive/2011/12/08/so-many-interfaces-part-two. aspx – phoog

11

Como una matriz no admite todas las características de un IList (Agregar/Eliminar/etc), IList.Count (y muchos otros métodos) se implementan de forma privada (explícitamente). Esto se puede ver en el desmontaje:

int ICollection.Count 

Si realmente quería utilizar Conde, que podría hacer

((IList)myArray).Count 
Cuestiones relacionadas