Je viens de remarquer qu'un tableau multidimensionnel en C # ne met pas en œuvre IEnumerable<T>
, alors qu'il applique IEnumerable
. Pour les tableaux monocensionnels, les deux IEnumerable<T>
et IEnumerable
sont mis en œuvre.
Pourquoi cette différence? Si une matrice multidimensionnelle est IEnumerable
, il devrait également également mettre en œuvre la version générique? J'ai remarqué cela parce que j'ai essayé d'utiliser une méthode d'extension sur une matrice multidimensionnelle, qui échoue à moins que vous n'utilisiez Cast<T>
ou similaire; Donc, je peux certainement voir un argument de fabrication de matrices multidimensionnelles implémenter IEnumerable<T>
.
Pour clarifier ma question dans le code, je m'attendrais à imprimer le code suivant true
quatre fois, alors qu'il imprime en fait 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);
Le CLR a deux types différents de matrices: vecteurs qui sont garantis à un dimensionnement avec une limite inférieure de 0 et plus de réseaux généraux pouvant avoir des limites non nuls et un rang autre que 0.
À partir de la section 8.9.1 de la spécification CLI:
De plus, un vecteur créé avec l'élément type T, implémente l'interface
System.Collections.Generic.IList<U>
(§8.7), où u: = T.
Je dois dire que ça me semble assez étrange. Étant donné qu'il implémente déjà IEnumerable
je ne vois pas pourquoi il ne devrait pas mettre en œuvre IEnumerable<T>
. Cela ne ferait pas autant de sens à mettre en œuvre IList<T>
, mais la simple interface générique irait bien.
Si vous le souhaitez, vous pourriez appeler Cast<T>
(si vous utilisez .NET 3.5) ou écrivez votre propre méthode à itérer via le tableau. Pour éviter de casting, vous devez écrire votre propre méthode qui a trouvé les limites inférieure/supérieure de chaque dimension et extraites des objets de cette façon. Pas terriblement agréable.
Il y a une solution de contournement: vous pouvez convertir n'importe quel tableau multidimensionnel en un iNeumable
public static class ArrayExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this Array target)
{
foreach (var item in target)
yield return (T)item;
}
}
Les matrices multidimensionnelles sont non tableaux aux fins de la hiérarchie de l'héritage. Ils sont un type complètement séparé. De plus, ce type n'a pas de bon soutien du cadre pour deux raisons possibles:
Dans le cas de IEnumerable
, comment cela devrait-il avoir été mis en œuvre, c'est-à-dire dans quel ordre les éléments devraient-ils être énumérées? Il n'y a pas d'ordre inhérent aux tableaux multidimensionnels.
Les tableaux de dimension unique nuls implémentent les deux IEnumerable
et IEnumerable<T>
, mais les tableaux multidimensionnels, malheureusement, implémentent uniquement IEnumerable
. La "solution de contournement" de @jader diaas convertit en effet un tableau multidimensionnel en IEnumerable<T>
Mais avec un coût énorme: chaque élément d'un tableau sera en boîte.
Voici une version qui ne provoquera pas de boxe pour chaque élément:
public static class ArrayExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this T[,] target)
{
foreach (var item in target)
yield return item;
}
}
Les matrices déchiquetées ne soutiennent pas IEnumerable<int>
Soit, car des structures multidimensionnelles ne sont pas vraiment un tableau d'un type, ils sont un tableau d'un tableau d'un type:
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 vrai, vrai, vrai, vrai.
NOTE: int[,]
n'est pas un IEnumerable<int[]>
, c'est pour les raisons spécifiées dans l'autre réponse, à savoir qu'il n'y a pas de moyen générique de savoir quelle dimension à parcourir. Avec des matrices déchiquetées, il n'y a pas autant de place à interprétation car la syntaxe est assez claire à ce sujet étant une gamme de tableaux.
Penser inversement. Le tableau 2D existe déjà. Juste l'énumérer. Créez un tableau 2D avec le score et le lieu d'un tableau initial ou des marques, y compris des valeurs dupliquées.
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();
Résultats:
Score Place
100 1
99 2
90 3
50 4
40 5
35 6
34 7
31 8
20 9
20 10
15 11