Alex Rivera | Logout

Why use .AsEnumerable() rather than casting to IEnumerable<T>?

Asked 2010-01-06T15:10:57.100
72

One of the extension methods on IEnumerable<T> is .AsEnumerable(). This method converts the enumerable object it was called on into an instance of IEnumerable<T>. However, since an object must implement IEnumerable<T> in order to apply to this extension method, converting to IEnumerable<T> is a simple matter of casting to IEnumerable<T>. My question is why does this method exist at all?

Example:

List<string> strings = new List<string>() { "test", "test2", "test3" };
IEnumerable<string> stringsEnum1 = strings.AsEnumerable();
IEnumerable<string> stringsEnum2 = (IEnumerable<string>)strings;

In the example above, stringsEnum1 and stringsEnum2 are equivalent. What's the point of the extension method?

As a corollary, why is there an .AsQueryable() method when casting to IQueryable<T> is equivalent?

Edit
Report

2 Answers

95

Readability is the main issue here. Consider that

Table.AsEnumerable().Where(somePredicate)

is far more readable than

((IEnumerable<TableObject>)Table).Where(somePredicate).

Or imagine wanting to execute part of the query on the SQL Server and the rest in memory:

Table.Where(somePredicate)
     .Select(someProjection)
     .AsEnumerable()
     .SomethingElse()

versus

((IEnumerable<SomeProjectionType>)Table.Where(somePredicate)
                                       .Select(someProjection))
                                       .SomethingElse()

Now, as for why such a method is useful at all, think of the example of a Table in a LINQ to SQL DataContext. As Table is an IQueryable, it implements IEnumerable. When you invoke a Where method on such a Table and enumerate through the results, code is executed that eventually causes a SQL statement to be executed on a SQL Server. What AsEnumerable does is says, no, I don't want to use the LINQ to SQL provider to execute the Where, I want to use the LINQ to Objects implementation of Where.

Thus enumerating over

Table.Where(somePredicate)

causes a query to be executed on a SQL Server whereas enumerating over

Table.AsEnumerable().Where(somePredicate)

brings the table represented by Table into memory and executes the Where functionality in memory (and not on the SQL Server!)

This is the point of AsEnumerable: to allow you to hide a specific implementation of IEnumerable methods and instead use the standard implementation.

answered 2010-01-06T15:15:40.690
16

I've thought of a reason apart from readability, though related to query implementation: using Linq to Objects on anonymous types returned via another Linq provider. You can't cast to an anonymous type (or a collection of anonymous types), but you can use .AsEnumerable() to perform the cast for you.

Example:

// Get an IQueryable of anonymous types.
var query = from p in db.PeopleTable /* Assume Linq to SQL */
            select new { Name = p.Name, Age = p.Age };

// Execute the query and pull the results into an IEnumerable of anonymous types
var @enum = query.AsEnumerable();

// Use Linq to Objects methods to further refine.
var refined = from p in @enum
              select new
              {
                  Name = GetPrettyName(p.Name),
                  DOB = CalculateDOB(p.Age, DateTime.Now)
              };

Clearly the reason here is that we want to use something like Linq to SQL to pull down some records into an anonymous type, then perform some custom logic (that wouldn't be possible via Linq to SQL) using Linq to Objects on the client-side.

Casting to IEnumerable<_anon> isn't possible, so .AsEnumerable() is the only way to go.

Thanks everyone who answered to help me piece this together. =)

answered 2010-01-06T15:46:09.493

Your Answer