Acabei de notar que um array multidimensional em C # não implementa IEnumerable
, enquanto implementa IEnumerable
. Para matrizes unidimensionais, IEnumerable
e IEnumerable
são implementados.
Por que essa diferença? Se uma multidimensional array é IEnumerable
, certamente também deve implementar a versão genérica? Eu notei isso porque tentei usar um método de extensão em um array multidimensional, que falha a menos que você use Cast
ou similar; então eu definitivamente posso ver o argumento para fazer matrizes multidimensionais implementar IEnumerable
.
Para esclarecer minha dúvida no código, esperaria que o código a seguir fosse impresso quatro vezes, enquanto na verdade ele imprime true
, false
, true
, true
:
int[] singleDimensionArray = new int[10]; int[,] multiDimensional = new int[10, 10]; Debug.WriteLine(singleDimensionArray is IEnumerable); Debug.WriteLine(multiDimensional is IEnumerable); Debug.WriteLine(singleDimensionArray is IEnumerable); Debug.WriteLine(multiDimensional is IEnumerable);
O CLR tem dois tipos diferentes de matrizes: vetores que são garantidos como unidimensionais com um limite inferior de 0 e matrizes mais gerais que podem ter limites diferentes de zero e um nível diferente de 0.
Da seção 8.9.1 da especificação do CLI:
Além disso, um vetor criado com o tipo de elemento T, implementa a interface
System.Collections.Generic.IList
(§8.7), onde U: = T.
Eu tenho que dizer que parece muito estranho para mim. Dado que ele já implementa IEnumerable
eu não vejo porque ele não deve implementar IEnumerable
. Não faria muito sentido implementar o IList
, mas a interface genérica simples estaria bem.
Se você quiser isso, você pode chamar Cast
(se você estiver usando o .NET 3.5) ou escrever seu próprio método para percorrer a matriz. Para evitar a transmissão, você teria que escrever seu próprio método, que encontrou os limites inferior / superior de cada dimensão, e buscou as coisas dessa maneira. Não muito agradável.
Existe uma solução: você pode converter qualquer array multidimensional para um IEnumerable
public static class ArrayExtensions { public static IEnumerable ToEnumerable (this Array target) { foreach (var item in target) yield return (T)item; } }
Matrizes multidimensionais não são matrizes para o propósito da hierarquia de inheritance. Eles são um tipo completamente separado. Além disso, esse tipo não tem um bom suporte da estrutura por dois possíveis motivos:
No caso de IEnumerable
, como isso deve ter sido implementado, ou seja, em que ordem os elementos devem ser enumerados? Não há ordem inerente aos arrays multidimensionais.
Matrizes unidimensionais de limite zero implementam IEnumerable
e IEnumerable
, mas matrizes multidimensionais, infelizmente, implementa apenas IEnumerable
. A “solução alternativa” de @Jader Dias de fato converte uma multidimensional array para IEnumerable
mas com um custo enorme: cada elemento de uma matriz será encaixotado.
Aqui está uma versão que não causará boxe para todos os elementos:
public static class ArrayExtensions { public static IEnumerable ToEnumerable (this T[,] target) { foreach (var item in target) yield return item; } }
Matrizes irregulares também não suportam IEnumerable
, porque estruturas multidimensionais não são realmente uma matriz de um tipo, elas são uma matriz de uma matriz de um tipo:
int[] singleDimensionArray = new int[10]; int[][] multiJagged = new int[10][]; Debug.WriteLine(singleDimensionArray is IEnumerable); Debug.WriteLine(multiJagged is IEnumerable); Debug.WriteLine(singleDimensionArray is IEnumerable); Debug.WriteLine(multiJagged is IEnumerable);
Imprime verdadeiro, verdadeiro, verdadeiro e verdadeiro.
Nota : int[,]
não é um IEnumerable
, que é pelas razões especificadas na outra resposta, ou seja, não há nenhuma maneira genérica de saber qual dimensão para iterar. Com arrays irregulares, não há muito espaço para interpretação, porque a syntax é bem clara sobre ser uma matriz de arrays.
Pense inversamente. A matriz 2d já existe. Apenas enumere. Crie uma matriz 2D com pontuação e local de uma matriz inicial ou marcas, incluindo valores duplicados.
int[] secondmarks = {20, 15, 31, 34, 35, 50, 40, 90, 99, 100, 20}; IEnumerable 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