When to use Cast() and OfType() in Linq
Asked Answered
G

7

273

I am aware of two methods of casting types to IEnumerable from an Arraylist in Linq and wondering in which cases to use them?

e.g

IEnumerable<string> someCollection = arrayList.OfType<string>()

or

IEnumerable<string> someCollection = arrayList.Cast<string>()

What is the difference between these two methods and where should I apply each case?

Gondolier answered 25/10, 2010 at 15:9 Comment(0)
P
412

OfType - return only the elements that can safely be cast to type x.
Cast - will try to cast all the elements into type x. if some of them are not from this type you will get InvalidCastException

EDIT
for example:

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }
Pocketbook answered 25/10, 2010 at 15:13 Comment(4)
cheers for that. Tried both beforehand but both had elements all of the type expected hence why I could not see the difference.Gondolier
@SLaks points out correctly that you should use Cast<T> when you know for sure that the collection contains only type T elements. OfType<T> is slower due to the is type check. If the collection is of type IEnumerable<T>, Cast<T> will simply cast the whole collection as IEnumerable<T> and avoid enumerating it; OfType<T> will still enumerate. ref: #11431070Jaime
Even in cases where .Cast<string>() does not throw when it is enumerated, it is not equivalent to .OfType<string>(). The reason is that null values are always skipped by .OfType<TResult>(). An example: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count() will give only 3; the similar expression with .Cast<string>() evaluates to 4.Measles
in other words, it's something like the difference between 'as' and 'cast' operatorsHyperparathyroidism
L
142

Source: LINQ Tip: Enumerable.OfType - Solutionizing .NET

Fundamentally, Cast<T>() is implemented like this:

public IEnumerable<T> Cast<T>(this IEnumerable source)
{
  foreach(object o in source)
    yield return (T) o;
}

Using an explicit cast performs well, but will result in an InvalidCastException if the cast fails. A less efficient yet useful variation on this idea is OfType<T>():

public IEnumerable<T> OfType<T>(this IEnumerable source)
{
  foreach(object o in source)
    if(o is T t)
      yield return t;
}

The returned enumeration will only include elements that can safely be cast to the specified type.

Leath answered 25/10, 2010 at 15:13 Comment(2)
I have provided an explicit operator, yet it still fails. Does the argument have to be of type object? My operator expects an argument of type T, T is the type of elements in the given IEnumerable.Tavish
I wonder if eating the exception rather than using is T would be more efficient for OfType<T> in cases where you're expecting most elements to be of type T. Might be worth benchmarking. foreach(object o in source) try { yield return t; } catch { }Camire
S
49

You should call Cast<string>() if you know that all of the items are strings.
If some of them aren't strings, you'll get an exception.

You should call OfType<string>() if you know that some of the items aren't strings and you don't want those items.
If some of them aren't strings, they won't be in the new IEnumerable<string>.

Spot answered 25/10, 2010 at 15:14 Comment(2)
This answer is (currently) the only one that gives an explicit advice when to use which method.Polytheism
Note that OfType<string>() will also skip null values. e.g: new string[] { "abc", "123", null, "" }.OfType<string>().Count() equals 3, whereas .Cast<string>().Count() would equal 4.Velure
G
8

It should be noted that Cast(Of T) can be used on IEnumerable unlike other LINQ functions, so if there's ever a case where you need to use LINQ on a non-generic collection or list such as an ArrayList, you can use Cast(Of T) to cast to an IEnumerable(Of T) where LINQ can work.

Gammadion answered 30/7, 2014 at 9:21 Comment(0)
P
2

Cast() will try to cast all elements of the collection (and will throw an exception if element is of the wrong type) while OfType() will return only elements of proper type.

Pacorro answered 25/10, 2010 at 15:13 Comment(0)
L
2

OfType will filter the elements to return only the ones of the specified type. Cast will crash if an element cannot be cast to the target type.

Lockett answered 25/10, 2010 at 15:14 Comment(0)
B
2

Cast<T> will try to cast all items to the given type T. This cast could fail or throw an exception. OfType<T> will return a subset of the original collection and return only objects that are of type T.

Bleak answered 25/10, 2010 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.