关于c#:何时在Linq中使用Cast()和Oftype()

When to use Cast() and Oftype() in Linq

我知道两种从LINQ中的ArraylistIEnumerable投射类型的方法,我想知道在哪种情况下使用它们?

例如

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

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

这两种方法的区别是什么?我应该在哪里应用每种情况?


OfType—只返回可以安全地强制转换为类型x的元素。Cast将尝试将所有元素强制转换为类型x。如果其中一些元素不是此类型的元素,您将得到InvalidCastException

编辑例如:

1
2
3
object[] objs = new object[] {"12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return {"12345" }


http://solutionioning.net/2009/01/18/linq-tip-enumerable-of类型/

从根本上讲,cast()的实现方式如下:

1
2
3
4
5
public IEnumerable<T> Cast<T>(this IEnumerable source)
{
  foreach(object o in source)
    yield return (T) o;
}

使用显式强制转换效果很好,但如果强制转换失败,将导致InvalidCastException。这个想法的一个效率较低但有用的变体是oftype():

1
2
3
4
5
6
public IEnumerable<T> OfType<T>(this IEnumerable source)
{
  foreach(object o in source)
    if(o is T)
      yield return (T) o;
}

返回的枚举将只包含可以安全地强制转换为指定类型的元素。


如果你知道所有的物品都是string,你应该打电话给Cast()。如果其中一些不是字符串,您将得到一个异常。

如果你知道有些物品不是string,而且你不想要这些物品,你应该打电话给OfType()。如果其中一些不是字符串,它们就不会出现在新的IEnumerable中。


需要注意的是,与其他Linq函数不同,Cast(Of T)可用于IEnumerable,因此,如果有需要在非通用集合或列表(如ArrayList上使用Linq的情况,可以使用Cast(Of T)来强制转换到Linq可以工作的IEnumerable(Of T)上。


Cast将尝试将所有项目强制转换为给定的T类型。此强制转换可能失败或引发异常。OfType将返回原始集合的一个子集,只返回T类型的对象。


OfType将过滤元素,只返回指定类型的元素。如果元素不能强制转换为目标类型,则Cast将崩溃。


Cast()将尝试强制转换集合的所有元素(如果元素的类型错误,则抛出异常),而OfType()将只返回正确类型的元素。