【问题标题】:Does .Where(x=> x.listFoos.Count() > 1) count all sub element?.Where(x=> x.listFoos.Count() > 1) 是否计算所有子元素?
【发布时间】:2020-09-10 11:35:48
【问题描述】:

给定一个具有 List 类型属性的对象列表:

class Bar{
   public List<Foo> Foos{get;set;}
}

以下代码是否会选择所有包含多个 Foo 的条形图,计算所有 Foos?
还是会在 2 Foos 时停止迭代?

var input = new List<Bar>();
var result = input.Where(x=> x.Foos.Count()>1).ToList();

【问题讨论】:

  • 代码,如图所示,不会计算任何 Foos,因为 Where 是惰性求值的。
  • 另一种方法是使用input.Skip(1).Any(),以防止迭代整个可枚举(即当它不是ICollection&lt;T&gt; 时)。
  • 在使用 LinQ Count() 时,您希望枚举某些内容。在 Where 子句中限制此计数“是否有多个项目?”期望只计数到 1 是正常的。这与问题的计数相矛盾。
  • @Enigmativity:我冒昧地将您的评论添加到我的答案中(太有用了,不能在评论中丢失)。

标签: c# linq


【解决方案1】:

它不会计算任何东西。 List&lt;T&gt; 冗余存储元素的数量,因此访问Count 属性is a O(1) operation

即使您使用Enumerable.Count() 扩展方法而不是List&lt;T&gt;s 内置Count 属性,这也有效,因为如果基础数据源实现ICollection&lt;T&gt;Enumerable.Count() has a built-in optimization


正如 cmets 中的 Enigmativity 所提到的:如果您有一个 不是ICollection&lt;T&gt; 的 IEnumerable,则可以改用以下内容来防止迭代整个 enumerable:

var result = input.Where(x => x.Foos.Skip(1).Any()).ToList();

【讨论】:

  • 我期待的是:“不,这不算数”。但我希望它是因为在某种表达式树中, this 屈服于 that ,并且它停止枚举。不计数不依赖 ICollection。
  • @DragandDrop:据我所知,LINQ-to-objects(相对于 LINQ-to-SQL 或 EF)不使用表达式树评估。因此,Count() 要么被执行,要么不被执行,如果它被执行,它将不知道使用它的上下文 (... &gt; 1)。
  • 对于System.Collections 中的所有内容,这几乎是所有轻触的内容,这不会因为optimisation。我可能很简单,我“预期”计数和 linQ 是被评估的树。但是 C# dev 比我聪明,这里的 count 比 skip().any 快,因为它是一个简单的类型检查,访问属性与 getEnumerator 等。所以即使它知道上下文也不需要。
  • 当我说我没想到时,我并没有以任何方式反对这个答案。我有一个简单的 Where Count,并问自己也许它很重要。但事实并非如此。我幻想它如何解决它没有的问题。
【解决方案2】:

当您对 .Net 的各个部分如何工作有疑问时,最好查看 source code

这是 List.Count 的来源

    // Read-only property describing how many elements are in the List.
    public int Count {
        get {
            Contract.Ensures(Contract.Result<int>() >= 0);
            return _size; 
        }
    }

_size 会随着基础集合的更改而更改,因此它实际上并不计算它只是引用列表的已知大小。

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 2018-10-08
    • 2019-03-09
    • 2023-04-10
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 2020-02-21
    相关资源
    最近更新 更多