recorrer - ¿Qué interfaces implementan todas las matrices en C#?
matriz en c# consola (5)
Comenzando con .NET 4.5, las matrices también implementan las interfaces System.Collections.Generic.IReadOnlyList<T>
y System.Collections.Generic.IReadOnlyCollection<T>
.
Por lo tanto, al usar .NET 4.5, la lista completa de interfaces implementadas por matrices se convierte (obtenida utilizando el método presentado en la respuesta de Hosam Aly ):
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
System.Collections.Generic.IReadOnlyList`1[System.Int32]
System.Collections.Generic.IReadOnlyCollection`1[System.Int32]
Extrañamente, parece que se olvidó actualizar la documentation para mencionar estas dos interfaces.
Como nuevo programador de .NET 3.5, comencé a aprender LINQ y encontré algo bastante básico que no había notado antes:
El libro afirma que cada matriz implementa IEnumerable<T>
(obviamente, de lo contrario no podríamos usar LINQ para objetos en matrices ...). Cuando vi esto, pensé que nunca pensé en eso, y me pregunté qué más implementarían todas las matrices, así que examiné System.Array
usando el buscador de objetos (ya que es la clase base para cada matriz en la CLR) y, para mi sorpresa, no implementa IEnumerable<T>
.
Entonces mi pregunta es: ¿dónde está la definición? Quiero decir, ¿cómo puedo decir exactamente qué interfaces implementa cada matriz?
Con cuidado en las interfaces de matriz, pueden implementarlas, pero en realidad no lo hacen ... Haga una conexión en el siguiente código:
var x = new int[] { 1, 2, 3, 4, 5 };
var y = x as IList<int>;
Console.WriteLine("The IList:" + string.Join(",", y));
try
{
y.RemoveAt(1);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.WriteLine(string.Join(",", y));
Produce la siguiente salida: result
Entonces, el análisis funciona, pero no todo es compatible, lo que es correcto desde la perspectiva de la colección de longitud fija, pero bastante erróneo si realmente crees que se trata de una lista. Ahí va el principio de Liskov de SÓLIDO :(.
Para las pruebas rápidas this ayudará.
De la documentation (énfasis mío):
[...] la clase Array implementa las interfaces genéricas
System.Collections.Generic.IList<T>
,System.Collections.Generic.ICollection<T>
ySystem.Collections.Generic.IEnumerable<T>
. Las implementaciones se proporcionan a las matrices en tiempo de ejecución y, por lo tanto, no son visibles para las herramientas de creación de documentación.
EDITAR: como señala Jb Evain en su comentario, solo los vectores (matrices unidimensionales) implementan las interfaces genéricas. En cuanto a por qué las matrices multidimensionales no implementan las interfaces genéricas, no estoy muy seguro ya que implementan las contrapartes no genéricas (vea la declaración de clase a continuación).
La clase System.Array
(es decir, cada matriz) también implementa estas interfaces no genéricas:
public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable
He encontrado la implementación de IList<T>, ICollection<T>, IEnumerable<T>
en la clase anidada SZArrayHelper
de la matriz.
Pero tengo que advertirte, allí encontrarás muchas más preguntas ...
Después de eso, tengo solo uno - there_is_no_array;)
Puede encontrar la respuesta a su pregunta empíricamente utilizando un pequeño fragmento de código:
foreach (var type in (new int[0]).GetType().GetInterfaces())
Console.WriteLine(type);
La ejecución del fragmento de arriba generaría la siguiente salida (en .NET 4.0):
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
( `1
significa <T>
)