BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

LINQ
.NET 3.5+

LINQ Conversion

The thirteenth part of the LINQ to Objects tutorial describes some of the conversion operators provided by Language-Integrated Query (LINQ). These operators allow you to convert between sequence types or cast the elements of a sequence to another type.

AsEnumerable

The last standard query operator in this section is AsEnumerable. This method takes a class that implements IEnumerable<T> and returns an object of a class that also implements IEnumerable<T>. However, the operation is not the same as simply casting the collection type or using the as keyword. The returned value is potentially of a different underlying type to the original.

One of the key uses of AsEnumerable is to change the type of a class that uses alternative versions of standard query operators. For example, when using the Where operator with LINQ to SQL to filter a set of data, the resultant information may be generated by reading data from a SQL Server database. This round-trip to the server may lower the performance of a query for which all of the data is already held in memory. By converting the source using AsEnumerable, the Where call will use the standard filtering rather than the database-specific implementation, potentially improving performance hugely. Of course, this assumes that no round-trip to the database is required to achieve the correct results.

When using the sample data created earlier there is little effect from calling AsEnumerable. The syntax is shown below for completeness.

IEnumerable<int> converted = list.AsEnumerable();

Working with the Types of Items in a Sequence

The remainder of this article will consider two standard query operators that perform actions upon the individual items within a collection, generating a new IEnumerable<T> containing those items, or modified versions thereof. To complete the demonstrations we need some further sample data. This will use non-generic ArrayList collections so ensure that you include the following using directive in your source code:

using System.Collections;

We can now add the two ArrayLists that will be used in the examples:

ArrayList arrayList = new ArrayList { 1, 2, 3, 4, 5, 6 };
ArrayList mixed = new ArrayList { 1, 2, 3, "D", "E", "F" };

Cast

The Cast standard query operator allows all of the items within an existing collection to be cast to another type and returned in a new collection that implements IEnumerable<T>. The method uses deferred execution.

To demonstrate, try executing the following code. This casts all of the items in the array from the original samples to objects.

IEnumerable<object> converted = array.Cast<object>();

The process of casting can fail with an InvalidCastException if the cast is invalid. For example, it is not valid to cast from int to string. However, this can be hidden to some extent by the deferred nature of execution. If you run the following code but do not read the results immediately, the exception will not be thrown immediately. Instead it will occur when the first resultant item that cannot be cast is read.

IEnumerable<string> converted = arrayList.Cast<string>();

Another use of Cast is to create a generically typed sequence from the contents of a non-generic collection, allowing it to be used with further LINQ operators. The following sample shows this by creating a sequence of integers from one of the ArrayLists.

IEnumerable<int> converted = arrayList.Cast<int>();

OfType

The last standard query operator that we will examine is OfType. In some ways this operator is similar to the Cast method. It cycles through all of the items in a collection, casts them to a specified type and adds them to a new sequence. However, unlike Cast, if an item cannot be converted to the desired type no exception is thrown. Instead, the item is excluded from the results. This means that OfType filters a list to extract only the items that may be cast to a given type.

The last sample creates two new IEnumerable<T> instances. The first line extracts all of the strings from the ArrayList containing multiple data types. The second retrieves the integers. NB: OfType uses deferred execution so the results must be read before the operation actually occurs.

IEnumerable<string> strings = mixed.OfType<string>();
IEnumerable<int> integers = mixed.OfType<int>();
27 September 2010