CSharp - LINQ OfType

Introduction

The OfType operator can build an output sequence containing only the elements that can be successfully cast to a specified type.

Prototypes

public static IEnumerable<T> OfType<T>(
        this IEnumerable source);

OfType operator first argument, named source, is of type IEnumerable, not IEnumerable<T>.

Most of the deferred Standard Query Operators' first arguments are of type IEnumerable<T>.

OfType operator is designed to be called on classes that implement the IEnumerable interface, as opposed to the IEnumerable<T> interface.

You can call the OfType operator on a legacy collection as long as it implements IEnumerable, and an IEnumerable<T> output sequence will be created.

OfType operator differs from the Cast operator.

Cast operator will attempt to cast every element of the input sequence to type T and yield it to the output sequence.

If the cast fails, an exception is thrown.

The OfType operator will attempt to yield the input element only if it can be cast to type T.

The element must return true for element e is T for the element to be yielded to the output sequence.

Exceptions

ArgumentNullException is thrown if the source argument is null.

The following code is going to create an ArrayList containing objects of our two common classes, Student and StudentOptionEntry.

Once we have the ArrayList populated with objects of both classes, we will first call the Cast operator to show how it fails in this circumstance.

We will follow that call with a call to the OfType operator showing its function in the same situation.

Demo

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
class Program/* w  ww . j a  va  2s .c  o m*/
{
    static void Main(string[] args)
    {
        ArrayList al = new ArrayList();
        al.Add(new Student { id = 1, firstName = "Joe", lastName = "Ruby" });
        al.Add(new Student { id = 2, firstName = "Windows", lastName = "Python" });
        al.Add(new StudentOptionEntry { id = 1, optionsCount = 0 });
        al.Add(new StudentOptionEntry { id = 2, optionsCount = 99999999999 });
        al.Add(new Student { id = 3, firstName = "Application", lastName = "HTML" });
        al.Add(new StudentOptionEntry { id = 3, optionsCount = 848475745 });

        var items = al.Cast<Student>();

        Console.WriteLine("Attempting to use the Cast operator ...");
        try
        {
            foreach (Student item in items)
                Console.WriteLine("{0} {1} {2}", item.id, item.firstName, item.lastName);
        }
        catch (Exception ex)
        {
            Console.WriteLine("{0}{1}", ex.Message, System.Environment.NewLine);
        }

        Console.WriteLine("Attempting to use the OfType operator ...");
        var items2 = al.OfType<Student>();
        foreach (Student item in items2)
            Console.WriteLine("{0} {1} {2}", item.id, item.firstName, item.lastName);

    }
}
class Student
{
    public int id;
    public string firstName;
    public string lastName;

    public static ArrayList GetStudentsArrayList()
    {
        ArrayList al = new ArrayList();

        al.Add(new Student { id = 1, firstName = "Joe", lastName = "Ruby" });
        al.Add(new Student { id = 2, firstName = "Windows", lastName = "Python" });
        al.Add(new Student { id = 3, firstName = "Application", lastName = "HTML" });
        al.Add(new Student { id = 4, firstName = "David", lastName = "Visual" });
        al.Add(new Student { id = 101, firstName = "Kotlin", lastName = "Fortran" });
        return (al);
    }

    public static Student[] GetStudentsArray()
    {
        return ((Student[])GetStudentsArrayList().ToArray());
    }
}

class StudentOptionEntry
{
    public int id;
    public long optionsCount;
    public DateTime dateAwarded;

    public static StudentOptionEntry[] GetStudentOptionEntries()
    {
        StudentOptionEntry[] empOptions = new StudentOptionEntry[] {
      new StudentOptionEntry {
        id = 1,
        optionsCount = 2,
        dateAwarded = DateTime.Parse("1990/12/31") },
      new StudentOptionEntry {
        id = 2,
        optionsCount = 3000,
        dateAwarded = DateTime.Parse("1992/06/30")  },
      new StudentOptionEntry {
        id = 2,
        optionsCount = 3000,
        dateAwarded = DateTime.Parse("1991/01/01")  },
      new StudentOptionEntry {
        id = 3,
        optionsCount = 5000,
        dateAwarded = DateTime.Parse("1997/09/30") },
      new StudentOptionEntry {
        id = 2,
        optionsCount = 3000,
        dateAwarded = DateTime.Parse("2000/04/01")  },
      new StudentOptionEntry {
        id = 3,
        optionsCount = 7500,
        dateAwarded = DateTime.Parse("1998/09/30") },
      new StudentOptionEntry {
        id = 3,
        optionsCount = 7500,
        dateAwarded = DateTime.Parse("1998/09/30") },
      new StudentOptionEntry {
        id = 4,
        optionsCount = 2456,
        dateAwarded = DateTime.Parse("1997/12/31") },
      new StudentOptionEntry {
        id = 101,
        optionsCount = 2,
        dateAwarded = DateTime.Parse("1998/12/31") }
    };

        return (empOptions);
    }
}

Result

We wrapped the foreach loop that enumerates the query results with a try/catch block.

An exception will be thrown since there are objects of two completely different types.

We call the OfType operator and enumerate and display its results.

Related Topics