使用Linq处理二维数组时,出现Select未找到的问题

31

我想使用Linq查询一个二维数组,但是出现了错误:

找不到' SimpleGame.ILandscape [] '类型的源类型的查询模式实现。 'Select'未找到。 您是否缺少对'System.Core.dll'的引用或对'System.Linq'的使用指令?

以下是代码:

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

我已经确认我包含了引用 System.Core 并使用了 System.Linq

有人能给出一些可能的原因吗?


此外,这个.map实现了IEnumerable/IQueryable吗? - Matthew Abbott
@Matthew Abbott:嗯,这是一个二维数组,所以我猜微软的一些人实现了它。 - LLS
请参考此答案:https://dev59.com/p0jSa4cB1Zd3GeqPCAyt - Stephen Cleary
2个回答

44

为了在LINQ中使用你的多维数组,你只需要将它转换成IEnumerable<T>。这很简单,下面是两个查询示例:

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;

每种语法都会将2D数组转换为IEnumerable<T>(因为你在一个from子句中说了int item或者在另一个中使用了array.Cast<int>())。然后,您可以使用LINQ方法过滤、选择或执行任何所需的投影。


1
比我的代码更加简洁(除非需要自定义枚举行为) ;) - Ron Warholic
谢谢。我认为我可以在多维数组中使用foreach,C#是否也将其转换为IEnumerable<T>以使foreach工作? - LLS
2
@LLS,IEnumerable<T>foreach循环结构中并不是必需的。Array实现了IEnumerable,这符合要求。对于foreach,结构需要实现/隐式转换为可枚举接口(IEnumerableIEnumerable<T>)或具有适当的GetEnumeratorMoveNext方法。有关更多详细信息,请参见C#语言规范的第8.8.4节。 - Anthony Pegram

21

您的地图是一个多维数组,这些数组不支持LINQ查询操作(更多信息请参见为什么C#的多维数组没有实现IEnumerable<T>?

您需要将数组的存储方式扁平化(这可能是许多原因中最好的方法),或者编写一些自定义的枚举代码:

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];
    }
  }
}

我只看到yield return在GetEnumerator中使用,它是否也可以用于返回IEnumerable<T>? - LLS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接