5

How would I use the following LINQ query correctly? I want to create a one-dimensional array that contains only values that are greater than 5. I can't understand why it can't iterate over this multidimensional array, but if I use foreach, it actually iterates.

// 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;

The error is:

Could not find an implementation of the query pattern for source type 'int[*,*]'. 'Where' not found. Are you missing a reference or a using directive for 'System.Linq'?

I thought this might fix the problem:

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

But it doesn't implement the iterator.

0

1 Answer 1

11

The problem is that multi-dimensional (rectangular) arrays implement IEnumerable, but not IEnumerable<T>. Fortunately, you can use Cast to fix that - and Cast gets called automatically if you explicitly specify the type of the range variable:

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

Or without the unnecessary brackets:

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

Or using method calls directly, given that it's a pretty trivial query expression:

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

I think this will box each element, however. You could add your own Cast extension method to avoid that:

public static class RectangularArrayExtensions
{
    public static IEnumerable<T> Cast<T>(this T[,] source)
    {
        foreach (T item in source)
        {
            yield return item;
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

"Cast gets called automatically if you explicitly specify the type of the range variable" In 7 years of working with Linq I have never seen that. I assume that's in the spec somewhere?
@DStanley: Yup, see section 7.16.2.2 of the MS C# 5 spec.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.