2014-11-29 2 views
4

Как правильно использовать следующий запрос LINQ? Я хочу создать одномерный массив, который содержит только значения, которые больше 5. Я не могу понять, почему он не может перебирать этот многомерный массив, но если я буду использовать «foreach», он фактически перебирает.Запрос C# LINQ на многомерном массиве

 // Create an multidimensional array, then just put numbers into it and print the array. 
     int[,] myArr = new int[5,6]; 
     int rows = myArr.GetLength(0); 
     int cols = myArr.GetLength(1); 
     for (int i = 0; i < rows; i++) 
     { 
      for (int k = 0; k < cols; k++) 
      { 
       myArr[i,k] = i + k; 
       Console.Write(myArr[i,k]); 
      } 
      Console.WriteLine(""); 

     } 
     var highList = from val in myArr where (val > 5) select val; 

Ошибка: Ошибка 1 Не удалось найти реализацию шаблона запроса для исходного типа "ИНТ [,]. «Где» не найдено. Вам не хватает ссылки или директивы по использованию для «System.Linq»?

Я думал, что это могло бы решить эту проблему:

public static IEnumerator<int> GetEnumerator(int[,] arr) 
    { 
    foreach(int i in arr) 
    { 
     yield return i; 
    } 
    } 

Но я предполагаю, что это на самом деле не реализовать итератор. Извините, если я говорю о странных вещах здесь, я как бы новичок в этих вещах ... Спасибо.

ответ

10

Проблема в том, что многомерные (прямоугольные) массивы реализуют IEnumerable, но не IEnumerable<T>. К счастью, вы можете использовать Cast, чтобы исправить это - и Cast вызывается автоматически, если вы явно указать тип переменной диапазона:

var highList = from int val in myArr where (val > 5) select val; 

Или без лишних скобок:

var highList = from int val in myArr where val > 5 select val; 

Или с помощью метода вызовов непосредственно, учитывая, что это довольно тривиальное выражение запроса:

var highList = myArr.Cast<int>().Where(val => val > 5); 

Я думаю это будет каждый элемент. Вы можете добавить свой собственный методCast расширения, чтобы избежать этого:

public static class RectangularArrayExtensions 
{ 
    public static IEnumerable<T> Cast<T>(this T[,] source) 
    { 
     foreach (T item in source) 
     { 
      yield return item; 
     } 
    } 
} 
+0

«Cast вызывается автоматически, если вы явно указать тип переменной диапазона» За 7 лет работы с Linq я никогда не видел этого. Я предполагаю, что это где-то в спецификации? –

+0

@DStanley: Да, см. Раздел 7.16.2.2 спецификации MS C# 5. –