何时在 Linq 中使用 Cast() 和 Oftype()

Posted

技术标签:

【中文标题】何时在 Linq 中使用 Cast() 和 Oftype()【英文标题】:When to use Cast() and Oftype() in Linq 【发布时间】:2010-10-25 15:09:15 【问题描述】:

我知道在 Linq 中将类型转换为 IEnumerable 的两种方法从 Arraylist 并想知道在哪些情况下使用它们?

例如

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

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

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

【问题讨论】:

【参考方案1】:

OfType - 仅返回可以安全地转换为类型 x 的元素。Cast - 将尝试将所有元素转换为类型 x。如果其中一些不是这种类型,你会得到InvalidCastException

编辑 例如:

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

【讨论】:

为此欢呼。事先都尝试过,但两者都有预期的所有类型的元素,因此我看不到差异。 @SLaks 正确地指出,当您确定集合仅包含 T 类型元素时,您应该使用 Cast&lt;T&gt;。由于is 类型检查,OfType&lt;T&gt; 速度较慢。如果集合是IEnumerable&lt;T&gt; 类型,Cast&lt;T&gt; 将简单地将整个集合转换为IEnumerable&lt;T&gt; 并避免枚举它; OfType&lt;T&gt; 仍将枚举。参考:***.com/questions/11430570/… 即使.Cast&lt;string&gt;()在枚举时不抛出,它等同于.OfType&lt;string&gt;()。原因是 null 总是被.OfType&lt;TResult&gt;() 跳过。一个例子:new System.Collections.ArrayList "abc", "def", null, "ghi", .OfType&lt;string&gt;().Count() 只会给3;与 .Cast&lt;string&gt;() 类似的表达式的计算结果为 4 换句话说,有点像'as'和'cast'操作符的区别【参考方案2】:

来源:LINQ Tip: Enumerable.OfType - Solutionizing .NET

基本上,Cast&lt;T&gt;() 是这样实现的:

public IEnumerable<T> Cast<T>(this IEnumerable source)

  foreach(object o in source)
    yield return (T) o;

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

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

  foreach(object o in source)
    if(o is T)
      yield return (T) o;

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

【讨论】:

【参考方案3】:

如果您知道所有项目都是strings,则应致电Cast&lt;string&gt;()。 如果其中一些不是字符串,你会得到一个异常。

如果您知道某些项目不是 strings 并且您不想要这些项目,您应该致电 OfType&lt;string&gt;()。 如果其中一些不是字符串,它们将不会出现在新的 IEnumerable&lt;string&gt; 中。

【讨论】:

这个答案是(目前)唯一一个明确建议何时使用哪种方法的答案。 请注意,OfType&lt;string&gt;() 也将跳过 null 值。例如:new string[] "abc", "123", null, "" .OfType&lt;string&gt;().Count() 等于 3,而 .Cast&lt;string&gt;().Count() 将等于 4【参考方案4】:

需要注意的是,Cast(Of T) 可以在 IEnumerable 上使用,这与其他 LINQ 函数不同,因此,如果您需要在非泛型集合或列表(例如 ArrayList)上使用 LINQ,您可以使用 Cast(Of T) 转换为 LINQ 可以工作的 IEnumerable(Of T)

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

OfType 将过滤元素以仅返回指定类型的元素。 Cast 会在一个元素不能被转换为目标类型时崩溃。

【讨论】:

【参考方案7】:

Cast&lt;T&gt; 将尝试将所有项目转换为给定类型T。此转换可能会失败或引发异常。 OfType&lt;T&gt; 将返回原始集合的子集,并且只返回 T 类型的对象。

【讨论】:

以上是关于何时在 Linq 中使用 Cast() 和 Oftype()的主要内容,如果未能解决你的问题,请参考以下文章

何时何地使用 LINQ to Objects?

何时使用 .First 以及何时将 .FirstOrDefault 与 LINQ 一起使用?

LINQ:何时使用SingleOrDefault与FirstOrDefault()一起使用过滤条件

linq中AsEnumerable和AsQueryable的区别

为啥 Linq Cast<> 助手不能与隐式转换运算符一起使用?

linq中AsEnumerable和AsQueryable的区别