Pregunta

Acabo de notar que una matriz multidimensional en C # no implementa IEnumerable < T > , mientras que implementa IEnumerable . Para las matrices unidimensionales, se implementan IEnumerable < T > y 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 intenté 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 imprima true cuatro veces, mientras que en realidad 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);
¿Fue útil?

Solución

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 diferente de 0.

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

  

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

Tengo que decir que me parece bastante raro. 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 quiere esto, puede llamar a Cast < T > (si está usando .NET 3.5) o escribir su propio método para iterar a través de la matriz. Para evitar la conversión, tendría que escribir su propio método que encontrara los límites inferior / superior de cada dimensión y buscara las cosas de esa manera. No es terriblemente agradable.

Otros consejos

Hay una solución alternativa: puede convertir cualquier matriz multidimensional en 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 multidimensionales son no matrices a los efectos 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:

  • No es realmente tan útil. El único uso real para matrices multidimensionales es matrices. Para casi cualquier otra cosa, otras estructuras de datos (por ejemplo, matrices irregulares) son más adecuadas.
  • No es trivial diseñar 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 un orden inherente a las matrices multidimensionales.

Las matrices unidimensionales unidas a cero implementan tanto IEnumerable como IEnumerable < T > , pero desafortunadamente, las matrices multidimensionales solo implementan IEnumerable . La " solución " by @Jader Dias de hecho convierte 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á 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 irregulares tampoco admiten IEnumerable < int > , porque las estructuras multidimensionales no son realmente una matriz de un tipo, 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 [] > , eso es por las razones especificadas en el otro respuesta, a saber, no hay una forma genérica de saber sobre 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 es una matriz de matrices.

Piensa inversamente. La matriz 2d ya existe. Solo enumerarlo. Cree una matriz 2d con puntaje y lugar de una matriz o marcas iniciales, incluidos 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 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top