다음을 통해 공유


Use of “Enumerable.Cast” and “Enumerable.OfType” in C#

There are situations where you have a collection that doesn’t support LINQ and you want to run some LINQ query against a particular object or set of objects inside your  collection. Enumerable.Cast<TResult> and  Enumerable.OfType<TResult> methods are real life savers in those kind of situations. In this post let’s see how we can use Enumerable.Cast<TResult> and  Enumerable.OfType<TResult> to make use of LINQ on a collection which doesn’t support LINQ.

Let’s go by an example. I have created a console application. There I have the following class “Employee”.

public class Employee
{
    public int EmployeeId { get; set; }
    public string FullName { get; set; }
}

Then I have a simple ArrayList which will contain set of Employee objects.

ArrayList oArrayList = new ArrayList()
{
    new Employee()
    {
        EmployeeId=1,FullName="Jaliya Udagedara"
    },
    new Employee()
    {
        EmployeeId=2,FullName="Martin Smith"
    },
};

Now let’s say I want to query my ArrayList to find all the Employees where his/her FullName starts with the letter “J”. As you might already know ArrayList is a non-generic IEnumerable collection where basically you can store almost anything. Now let’s consider the following LINQ query.

var query = from e in oArrayList
            where e.FullName.StartsWith("J")
            select e;

This won’t even compile, I am getting the following error:  “Could not find an implementation of the query pattern for source type 'System.Collections.ArrayList'.  'Where' not found.  Consider explicitly specifying the type of the range variable 'e'”. That’s because ArrayList is a non-generic collection and you don’t know the types of the elements which are in my ArrayList.

For that I can write the following LINQ query using query syntax.

var query = from Employee e in oArrayList
            where e.FullName.StartsWith("J")
            select e;

Here I have explicitly declared the type of the range variable (Employee is the type of range variable e) to reflect the specific type of the objects in my ArrayList. When I put the type of the range variable, it is equal to calling the Enumerable.Cast<TResult>.

Enumerable.Cast<TResult> Method

What Enumerable.Cast<TResult> does is, it casts the elements of an IEnumerable to the type specified in TResult. If an element cannot be cast to type TResult, this method will throw an InvalidCastException.

So if I write the following LINQ query it would be same as the above query.

Query Syntax

var query = from e in oArrayList.Cast<Employee>()
            where e.FullName.StartsWith("J")
            select e;

Method Syntax

var query = oArrayList.Cast<Employee>()
                .Where(e => e.FullName.StartsWith("J"));

Now if we want to filter out the object that can be casted into type specified in TResult, we need to use Enumerable.OfType<TResult>.

Enumerable.OfType<TResult> Method

Enumerable.OfType<TResult> method filters the elements of an IEnumerable based on a type specified in TResult.

Now let’s consider the following ArrayList which consists of two strings, two integers, two Lists of type string and two objects of type “Employee”.

ArrayList oArrayList = new ArrayList()
{
    "Jaliya",
    "Smith",
    10,
    20,
    new List<string>() { "VS", "SQL" },
    new List<string>() { "VS", "Windows Azure" },
    new List<string>() { "Apple", "Orange" },
    new Employee()
    {
        EmployeeId=1,FullName="Jaliya Udagedara"
    },
    new Employee()
    {
        EmployeeId=2,FullName="Martin Smith"
    },
};
return oArrayList;

Now let’s say I want to filter out the elements  in my ArrayList using Enumerable.OfType<TResult>  method when TResult is of following types. I am putting some conditions on my queries and I don’t think I should be describing them all.

TResult is string

Query Syntax

IEnumerable<string> query = from s in oArrayList.OfType<string>()
                            where s.StartsWith("J")
                            select s;

Method Syntax

IEnumerable<string> query = oArrayList.OfType<string>()
                                .Where(s => s.StartsWith("J"));

TResult is List<string>

Query Syntax

IEnumerable<List<string>> query = from l in oArrayList.OfType<List<string>>()
                                  where l.Contains("VS")
                                  select l;

Method Syntax

IEnumerable<List<string>> query = oArrayList.OfType<List<string>>().
                                        Where(l => l.Contains("VS"));

TResult is Employee

Query Syntax

IEnumerable<Employee> query = from e in oArrayList.OfType<Employee>()
                              where e.FullName.StartsWith("J")
                              select e;

Method Syntax

IEnumerable<Employee> query = oArrayList.OfType<Employee>()
                                .Where(e => e.FullName.StartsWith("J"));

Hope you all got a good understanding on  Enumerable.Cast<TResult> Method and  Enumerable.OfType<TResult> Method.

I am uploading the full sample code to MSDN Code Gallery, enjoy.
   Download Sample

Happy Coding.