2010-06-30 12 views
14

quiero usar LINQ para consultar una matriz 2D, pero me da un error:Usando LINQ con matriz 2D, no seleccione encontró

Could not find an implementation of the query pattern for source type 'SimpleGame.ILandscape[,]'. 'Select' not found. Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'?

Código es el siguiente:

var doors = from landscape in this.map select landscape; 

He comprobado que incluí la referencia System.Core y usando System.Linq.

¿Alguien podría dar algunas posibles causas?

+0

Además, ¿this.map implementa IEnumerable/IQueryable? –

+0

@Matthew Abbott: Bueno, es una matriz 2D, así que supongo que algunas personas en Microsoft lo implementaron. – LLS

+0

posible duplicado de [¿Por qué C# matrices multidimensionales no implementa IEnumerable ?] (Http://stackoverflow.com/questions/275073/why-does-c-multidimensional-arrays-not-implement-ienumerablet) – ChrisF

Respuesta

22

con el fin de utilizar su matriz multidimensional con LINQ, sólo hay que convertirlo a IEnumerable<T>. Es bastante simple, aquí hay dos opciones de ejemplo para consultar

int[,] array = { { 1, 2 }, { 3, 4 } }; 

var query = from int item in array 
      where item % 2 == 0 
      select item; 

var query2 = from item in array.Cast<int>() 
       where item % 2 == 0 
       select item; 

Cada sintaxis convertirá la matriz 2D en un IEnumerable<T> (porque dices int item en una cláusula o de array.Cast<int>() en el otro). A continuación, puede filtrar, seleccionar o realizar cualquier proyección que desee con los métodos LINQ.

+1

+1 Mucho más conciso que el mío (a menos que necesite un comportamiento de enumeración personalizado);) –

+0

Gracias. Creo que puedo usar foreach en una matriz multidimensional, y ¿C# también la convierte en IEnumerable para hacer que foreach funcione? – LLS

+1

@LLS, 'IEnumerable ' no es necesario para la estructura de bucles 'foreach'. 'Array' implementa' IEnumerable', y esto se ajusta al requisito. Para el foreach, la estructura necesita implementar/ser implícitamente convertible a una interfaz enumerable ('IEnumerable' o' IEnumerable ') o tener los métodos apropiados' GetEnumerator' y 'MoveNext'. Ver la sección 8.8.4 de la especificación del lenguaje C# para más detalles. –

11

Su mapa es una matriz multidimensional - estos no son compatibles con operaciones de consulta de LINQ (ver mas Why do C# Multidimensional arrays not implement IEnumerable<T>?)

Tendrá que aplanan el almacenamiento para la matriz (probablemente el mejor camino a seguir por muchas razones) o escribir un código personalizado para ello enumeración:

public IEnumerable<T> Flatten<T>(T[,] map) { 
    for (int row = 0; row < map.GetLength(0); row++) { 
    for (int col = 0; col < map.GetLength(1); col++) { 
     yield return map[row,col]; 
    } 
    } 
} 
+0

Solo vi retorno de rendimiento en GetEnumerator, ¿funciona también para devolver un IEnumerable ? – LLS

+0

¡Claro que sí, pruébalo! –