C# 3.0 var keyword + Enumerable.AsEnumerable

On my way back from México, I read Pro LINQ: Language Integrated Query in C# 2008. Just like Charles Petzold first introducing WPF through code (and not markup), I like Joseph Rattz’ introduction of LINQ through [extension] methods first instead of the using query expressions. I do think this makes things easier to understand. For me at least. I did not like a big part of the book as it felt more like a reference book. But again, it’s just me.

One thing I disagree with his advice: page 27, he states that one should refrain from using the var keyword just because it’s convenient. I think that:

var integers = new List<int> { 1, 2, 3 };

is clear enough, no need for:

List<int> integers = new List<int> { 1, 2, 3 };

Also, on page 355, he states that strings will get boxed! Although an immutable type behaving like a value type, System.String is not a value type and will thus never be boxed. I guess he meant that the problem with c["Id"] == s["Id"] is that you’re comparing for equality of object reference you’re not comparing the content of the String instances.

Now, one thing I tend to forget when talking to developers is that some are still trying to grasp the idea of generics. And that’s exactly what I thought about when seeing Enumerable.AsEnumerable:

public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source) {

   return source;

}

Why would anyone need to use what looks to be such a useless code method? Look at this query expression:

var query = from dr in orderDataTable.AsEnumerable()

            select dr.Field<int>("OrderID");

If I’d like to cast OrderTable to a generic version of IEnumerable<T>, what value of T should I pick? In this example, the answer might be easy as DataTableExtensions.AsEnumerable(this DataTable source) returns an EnumerableRowCollection<DataRow> instance: we can cast to IEnumerator<DataRow>.

Both would work:

var query = from dr in (IEnumerable<DataRow>) orderDataTable

            select dr.Field<int>("OrderID");

and

var query = from dr in orderDataTable as IEnumerable<DataRow>

            select dr.Field<int>("OrderID");

But as soon as you have anonymous types involved, doing something like this is impossible: you don’t know the compiler generated name of those types! What would you use as the generic IEnumerable type parameter (you know, the T in IEnumerable<T>)?

The purpose of what looks like the simplistic Enumerable.AsEnumerable() method is hidden in its signature: the compiler will get you the right T to use in IEnumerable<T>, no need to know what it is.

OK. I’m no LINQ expert but by writing this, I’m clarifying my thoughts. I hope this helps.

Bonne nuit les petits.