30

I want to use Linq to query a 2D array but I get an error:

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'?

Code is following:

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

I've checked that I included the reference System.Core and using System.Linq.

Could anyone give some possible causes?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
LLS
  • 2,128
  • 2
  • 23
  • 36
  • Also, does this.map implement IEnumerable/IQueryable? – Matthew Abbott Jun 30 '10 at 15:23
  • @Matthew Abbott: Well, it's a 2D array, so I guess some people in Microsoft implemented it. – LLS Jun 30 '10 at 15:27
  • possible duplicate of [Why does C# Multidimensional arrays not implement IEnumerable ?](http://stackoverflow.com/questions/275073/why-does-c-multidimensional-arrays-not-implement-ienumerablet) – ChrisF Jun 30 '10 at 15:45
  • See this answer: http://stackoverflow.com/questions/1009019/c-select-unknown-item-from-multi-dimensional-array – Stephen Cleary Jun 30 '10 at 15:35

2 Answers2

43

In order to use your multidimensional array with LINQ, you simply need to convert it to IEnumerable<T>. It's simple enough, here are two example options for querying

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;

Each syntax will convert the 2D array into an IEnumerable<T> (because you say int item in one from clause or array.Cast<int>() in the other). You can then filter, select, or perform whatever projection you wish using LINQ methods.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • 1
    +1 Much more concise than mine (unless you need custom enumeration behavior) ;) – Ron Warholic Jun 30 '10 at 15:46
  • Thanks. I think I can use foreach in multidimensional array, and does C# also convert it to IEnumerable in order to make foreach work? – LLS Jul 01 '10 at 01:31
  • 2
    @LLS, `IEnumerable` is not required for the `foreach` looping structure. `Array` implements `IEnumerable`, and this fits the requirement. For the foreach, the structure needs to implement/be implicitly convertible to an enumerable interface (`IEnumerable` or `IEnumerable`) or have appropriate `GetEnumerator` and `MoveNext` methods. See section 8.8.4 of the C# language specification for more details. – Anthony Pegram Jul 02 '10 at 02:23
20

Your map is a multidimensional array--these do not support LINQ query operations (see more Why do C# Multidimensional arrays not implement IEnumerable<T>?)

You'll need to either flatten the storage for your array (probably the best way to go for many reasons) or write some custom enumeration code for it:

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];
    }
  }
}
Community
  • 1
  • 1
Ron Warholic
  • 9,994
  • 31
  • 47
  • I only saw yield return in GetEnumerator, does it also work to return an IEnumerable? – LLS Jul 01 '10 at 01:28