recorrer multidimensional matriz llenar jagged examples bidimensional arreglo array c# .net arrays multidimensional-array

matriz - ¿Por qué las matrices multidimensionales C#no implementan IEnumerable<T>?



multidimensional string array c# (6)

Me acabo de dar cuenta de que una matriz multidimensional en C # no implementa IEnumerable<T> , mientras implementa IEnumerable . Para arreglos unidimensionales, se IEnumerable<T> tanto IEnumerable<T> como IEnumerable .

¿Por qué esta diferencia? Si una matriz multidimensional es IEnumerable , seguramente también debería implementar la versión genérica? Me di cuenta de esto porque traté de usar un método de extensión en una matriz multidimensional, que falla a menos que use Cast<T> o similar; así que definitivamente puedo ver el argumento para hacer que las matrices multidimensionales implementen IEnumerable<T> .

Para aclarar mi pregunta en el código, esperaría que el siguiente código se imprimiera true cuatro veces, mientras que realmente se imprime true , false , true , true :

int[] singleDimensionArray = new int[10]; int[,] multiDimensional = new int[10, 10]; Debug.WriteLine(singleDimensionArray is IEnumerable<int>); Debug.WriteLine(multiDimensional is IEnumerable<int>); Debug.WriteLine(singleDimensionArray is IEnumerable); Debug.WriteLine(multiDimensional is IEnumerable);


El CLR tiene dos tipos diferentes de matrices: vectores que se garantiza que son unidimensionales con un límite inferior de 0 y matrices más generales que pueden tener límites distintos de cero y un rango distinto de 0.

De la sección 8.9.1 de la especificación CLI:

Además, un vector creado con elemento tipo T implementa la interfaz System.Collections.Generic.IList<U> (§8.7), donde U: = T.

Tengo que decir que me parece bastante extraño. Dado que ya implementa IEnumerable , no veo por qué no debería implementar IEnumerable<T> . No tendría mucho sentido implementar IList<T> , pero la interfaz genérica simple estaría bien.

Si quieres esto, puedes llamar a Cast<T> (si estás usando .NET 3.5) o escribir tu propio método para iterar a través de la matriz. Para evitar el lanzamiento, debe escribir su propio método, que encontró los límites inferior / superior de cada dimensión, y ha buscado las cosas de esa manera. No terriblemente agradable.


Hay una solución alternativa: puede convertir cualquier matriz multidimensional a un IEnumerable

public static class ArrayExtensions { public static IEnumerable<T> ToEnumerable<T>(this Array target) { foreach (var item in target) yield return (T)item; } }


Las matrices IEnumerable<int> tampoco admiten IEnumerable<int> porque las estructuras multidimensionales no son realmente una matriz de un tipo, sino que son una matriz de una matriz de un tipo:

int[] singleDimensionArray = new int[10]; int[][] multiJagged = new int[10][]; Debug.WriteLine(singleDimensionArray is IEnumerable<int>); Debug.WriteLine(multiJagged is IEnumerable<int[]>); Debug.WriteLine(singleDimensionArray is IEnumerable); Debug.WriteLine(multiJagged is IEnumerable);

Imprime verdadero, verdadero, verdadero, verdadero.

Nota : int[,] no es un IEnumerable<int[]> , por las razones especificadas en la otra respuesta, es decir, no hay una forma genérica de saber qué dimensión iterar. Con las matrices irregulares, no hay tanto espacio para la interpretación porque la sintaxis es bastante clara acerca de que se trata de una matriz de matrices.


Las matrices de dimensión única vinculadas a cero implementan tanto IEnumerable como IEnumerable<T> , pero las matrices multidimensionales, desafortunadamente, implementan solo IEnumerable . La "solución alternativa" de @Jader Dias convierte efectivamente una matriz multidimensional en IEnumerable<T> pero con un costo enorme: cada elemento de una matriz estará encuadrado.

Aquí hay una versión que no causará el boxeo para cada elemento:

public static class ArrayExtensions { public static IEnumerable<T> ToEnumerable<T>(this T[,] target) { foreach (var item in target) yield return item; } }


Las matrices multidimensionales no son matrices para el propósito de la jerarquía de herencia. Son un tipo completamente separado. Además, este tipo no tiene un buen soporte del marco por dos posibles razones:

  • En realidad no es tan útil. El único uso real para matrices multidimensionales es matrices. Para casi cualquier otra cosa, otras estructuras de datos (por ejemplo, arreglos irregulares) son más adecuadas.
  • No es trivial idear métodos genéricos y útiles para estas estructuras.

En el caso de IEnumerable , ¿cómo debería haberse implementado esto, es decir, en qué orden deberían enumerarse los elementos? No hay orden inherente en las matrices multidimensionales.


Piensa a la inversa. La matriz 2d ya existe. Solo enuémbrelo. Cree una matriz 2D con puntaje y lugar de una matriz inicial o marcas, incluidos los valores duplicados.

int[] secondmarks = {20, 15, 31, 34, 35, 50, 40, 90, 99, 100, 20}; IEnumerable<int> finallist = secondmarks.OrderByDescending(c => c); int[,] orderedMarks = new int[2, finallist.Count()]; Enumerable.Range(0, finallist.Count()).ToList().ForEach(k => {orderedMarks[0, k] = (int) finallist.Skip(k).Take(1).Average(); orderedMarks[1, k] = k + 1;}); Enumerable.Range(0, finallist.Count()).Select(m => new {Score = orderedMarks[0, m], Place = orderedMarks[1, m]}).Dump();

Resultados:

Score Place 100 1 99 2 90 3 50 4 40 5 35 6 34 7 31 8 20 9 20 10 15 11