ChatGPT解决这个技术问题 Extra ChatGPT

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

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

例如

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

或者

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

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


D
Dan Sinclair

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<T>。由于 is 类型检查,OfType<T> 速度较慢。如果集合是 IEnumerable<T> 类型,Cast<T> 将简单地将整个集合转换为 IEnumerable<T> 并避免枚举它; OfType<T> 仍将枚举。参考:stackoverflow.com/questions/11430570/…
即使在枚举时 .Cast<string>() 不抛出的情况下,它等同于 .OfType<string>()。原因是 null 总是被 .OfType<TResult>() 跳过。一个例子:new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count() 将只给出 3;具有 .Cast<string>() 的类似表达式的计算结果为 4
换句话说,这有点像“as”和“cast”运算符之间的区别
N
NotAPro

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

从根本上说,Cast<T>() 是这样实现的:

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

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

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

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


S
SLaks

如果您知道所有项目都是 string,则应调用 Cast<string>()
如果其中一些不是字符串,您将收到异常。

如果您知道某些项目不是 string 并且您不想要这些项目,则应调用 OfType<string>()
如果其中一些不是字符串,它们将不会出现在新的IEnumerable<string>


这个答案是(目前)唯一一个明确建议何时使用哪种方法的答案。
请注意,OfType<string>() 也会跳过 null 值。例如:new string[] { "abc", "123", null, "" }.OfType<string>().Count() 等于 3,而 .Cast<string>().Count() 将等于 4
T
T.S.

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


A
Andrew Bezzub

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


T
T.S.

OfType 将过滤元素以仅返回指定类型的元素。如果无法将元素强制转换为目标类型,Cast 将崩溃。


T
T.S.

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