【问题标题】:What's the performance hit of List.OfType<> where the entire list is that type?整个列表都是该类型的 List.OfType<> 对性能有何影响?
【发布时间】:2011-08-25 18:35:15
【问题描述】:

我有一个架构,我们将数据节点作为IEnumerable&lt;BaseNode&gt; 传递。这一切都很好,但在每个子类中,我们希望将它们存储为 List&lt;AnotherNode&gt;,因为该类中的所有内容都会创建和使用 AnotherNode 对象(我们有大约 15 个不同的子类)。

使用强类型列表不起作用的一个地方是根类方法返回类型 IEnumerable&lt;BaseNode&gt; 并且由于 .net 3.5 中的协方差限制,无法返回。 (我们现在必须使用 .net 3.5。)

但如果我有 List&lt;AnotherNode&gt; data; 并返回 data.OfType&lt;BaseNode&gt;(); - 那很好。所以这是我的问题。

由于所有数据都是 BaseNode 类型的 - 这个调用对性能有何影响?因为另一种选择是我必须在性能影响较小的地方进行投射——但这也是一种情况,我们知道它是类型就放弃一切。

【问题讨论】:

  • 我认为需要更多代码才能说出性能受到的影响。
  • 一般来说,性能成本太小了。等到你遇到真正的问题。
  • 如果您处于将项目转换为另一种类型成为性能问题的水平,那么您很可能处于更改架构更为重要的情况。
  • 只要记住在返回它之前调用 ToList 或 ToArray,如果这个结果使用了一个低。 OfType 返回一个 IEnumerable,它将在每次枚举每个元素时对其进行 OfType 工作。
  • @Henk Holterman - 打败我吧!

标签: c# linq generics covariance


【解决方案1】:

两件小事:

  1. 与产生枚举器中的每个项目相关联的开销很小,但可测量。如果您因为处于非常紧凑的内部循环中而需要关心这一点,那么实际上最好直接在列表上使用 for 循环进行迭代。很可能这无关紧要。

  2. 由于结果是 IEnumerable&lt;BaseNode&gt; 并且已经通过产生枚举函数进行过滤,因此对 Count() 或 ElementAt() 等方法的后续调用将不会利用列表的 LINQ 实现中的优化。除非您经常使用这些扩展方法并且拥有非常多的元素,否则这也不太可能成为问题。

【讨论】:

  • 第 2 点 +1。我以前没有考虑过,但很有意义。
  • 但是如果我返回 Cast().ToList() 那么我确实得到了正确的结果?
  • @David,正确,但在这种情况下,您会产生创建全新列表的开销。您希望使用 ToList() 的原因是,如果您希望返回值是数据的“快照”,而不是返回可用于重复枚举基础数据的上下文。
  • 所以这里没有完美的解决方案 - 哦,好吧......谢谢
【解决方案2】:

你见过Cast&lt;T&gt;() Linq 运算符吗?它应该比OfType&lt;T&gt;() 性能更高。

基本上有一个条件是用OfType&lt;T&gt;()运行的

if (item is T) {
    yield return (T)item;
}

Cast&lt;T&gt;() 所做的对比:

yield return (T)item;

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 2019-09-04
  • 2017-10-21
相关资源
最近更新 更多