是ConcurrentDictionary.Count> 0与ConcurrentDictionary.Any()相同?

时间:2015-04-01 19:33:02

标签: .net linq concurrentdictionary

如果我有一个ConcurrentDictionary实例,我是否使用Count属性或LINQ的Any()是否重要?我宁愿写dict.Any()而不是dict.Count > 0,因为我认为Any()更具描述性。

我只关心正确性,而不是表现。用例是

void process()
{
   if (concurrentDictionary.Count <= 0) // or !Any() ?
      return; // dictionary is empty, nothing to do

   // ...
}

3 个答案:

答案 0 :(得分:3)

问题Are IEnumerable Linq methods thread-safe?解决了LINQ查询的IEnumerable方法在没有保持集合保护的特定锁的情况下不是线程安全的事实。

您可以查看reference code for ConcurrentDictionary以查看枚举器未提供线程安全快照。其他ConcurrentDictionary.GetEnumerator州的MSDN文档:

  

从字典返回的枚举器可以安全地与字典的读写一起使用,但它并不代表字典的即时快照。通过枚举器公开的内容可能包含在调用GetEnumerator后对字典进行的修改

Count属性对字典进行完全锁定并返回一致的结果。

因此,根据您是否要锁定字典以运行Any(),检查Count > 0可能更为清晰。

答案 1 :(得分:2)

您必须对它们进行基准测试,因为Any()类似于

using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
    if (enumerator.MoveNext())
    {
        return true;
    }
}

return false;

所以它需要枚举,ConcurrentDictionary的内容很复杂,但即使Count的{​​{1}}也没有缓存,它似乎相当复杂。

我将添加ConcurrentDictionary必须仍然遍历一些内部结构(如在一个数组中)获取整个字典的锁定,而Count将停止在第一个非 - 空桶。我会说,对于一本大词典,Any()速度较慢,而对于较小的词典则速度较快。

更正:Count在计算之前获取所有字典的锁定。它会调用Count

请记住,在方法返回之前,两个方法的结果都可能被伪造,因为嘿......并发! : - )

答案 2 :(得分:1)

  

我是否使用Count属性或LINQ&#39; s Any()

是否重要

没有。它们在功能上是相同的,并且应该具有非常小的性能差异。使用任何最恰当地表达意义的内容,只有在存在对整个应用程序的性能有重大影响的性能问题时才更改它。

Count将在调用属性时计算字典中的项目。

Any会调用ConcurrentDictionary.GenEnumerator()来查看字典是否包含任何项目。根据{{​​3}},返回的枚举器将在调用GetEnumerator()后反映和更改字典。

因此,理论上如果在调用AnyMoveNext被调用Any之间添加项目,他们会计算得到不同的答案。然而,时间窗口应该很短,可能性应该非常小。

另外谁说谁是正确的?如果您可以在完全相同的时间<{1}}和Any 添加项目,那么该集合是否为空?