For the reasons that I still do not understand (see this SO question) multidimensional arrays in CLR do not implement IEnumerable
. So the following doe
The MSDN page for Array includes this:
Important Note: In the .NET Framework version 2.0, the Array class implements the System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, and System.Collections.Generic.IEnumerable<T> generic interfaces. The implementations are provided to arrays at run time,
Note the final words in the quote... it appears this generation does not happen for multi-dimensional arrays (so a documentation bug).
But as others have noted, what would T
be? A good case can be made for T[]
(or, these days with LINQ, IEnumerable<T>
).
In the end, if you want to iterate all the array's members just stick with IEnumerable and Cast<T> extension. Otherwise easy to write your own.
Samuel stated:
In C#, you can simulate this by using
var q = from e in m.Cast<object>() select e; // q is of type IEnumerable<object>
which is of course correct as far as mimicking VB in C# is concerned, but you would loose your type information. Instead, it is much easier and as it turns out, slightly better readable, to simply declare your range variable.
The following compiles, performs better, is type safe and does not loose type information:
var m = new int[2, 2] { { 1, 2 }, { 3, 4 } };
var q = from int e in m select e;
// q is of type IEnumerable<int>
In the original suggestion, you would have an IEnumerable<object>
, using int e
you change that into IEnumerable<int>
, which has its advantages.
The query works in VB.Net because it gets transformed into
IEnumerable<object> q = m.Cast<object>().Select<object, object>(o => o);
This works because you can call Cast<TResult>
() on IEnumerable
, which [*,*]
implements.
The LINQ query doesn't work in C# because of the different approach the C# and VB.Net designers took. VB.Net takes a more hand holding approach and fixes your mistake and converts IEnumerable
to IEnumerable<object>
so it can be used.
In C#, you can simulate this by using
var q = from e in m.Cast<object>() select e;
There are two reasons they don't implement it natively in C#:
yield
keyword, it just so easy to implement your own that's specific to your need at the time. Of course, that's a C# construct, but it's not that much harder in VB.