【问题标题】:ArrayList Count vs AnyArrayList 计数与任何
【发布时间】:2023-04-09 05:01:02
【问题描述】:

我正在查看一些遗留代码。该类使用 ArrayList 来保存项目。这些项目是从数据库表中获取的,最多可达 600 万个。该类公开了一个名为“ListCount”的方法来获取 Arraylist 中项目的计数。

Class Settings
{
    ArrayList settingsList ;
    public Settings()
    {
      settingsList = GetSettings();//Get the settings from the DB. Can also return null
    }

    public int ListCount
    {
        get
        {
           if (settingsList == null )
             return 0;
           else
             return settingsList.Count;
        }
    }
}

ListCount 用于检查列表中是否有项目。我想向班级介绍 'Any' 方法。

public bool Any(Func<vpSettings, bool> predicate)
{
   return settingsList !=null && settingsList.Cast<vpSettings>().Any(predicate);
}

问题是框架是否进行了某种优化并维护项目的计数,或者它是否遍历 Arraylist 以获取计数?是否建议添加上面的“任何”方法。

Marc Gravel 在以下问题中建议将 Any 用于 IEnumerable

Which method performs better: .Any() vs .Count() > 0?

【问题讨论】:

  • 你能显示GetSettings吗?例如,IListIDictionary 派生自 ICollection。这是额外的灵活性层的好处之一。 Array 应该有更少的开销并且更快。
  • @Greg..GetSettings() 做了很多事情并调用其他类中的方法最终从数据库中读取。老实说,该方法的代码到处都是。

标签: c# arraylist any


【解决方案1】:

.NET reference source 表示 ArrayList.Count 返回一个缓存的私有变量。

为了完整起见,the source 还在此处列出了 Any() 扩展方法的实现。本质上,扩展方法会进行 null 检查,然后尝试通过 IEnumerable 的枚举器获取第一个元素。

【讨论】:

  • 这是 Roslyn 项目中我最喜欢的东西之一 - 如果您以前没有见过它,还有一种方法可以将它与 Visual Studio 集成,以便您可以检查/单步执行编码。对于获得快速答案(或弄清楚结构)非常方便。这是more info
  • @Yogendra .NET 参考源本身并非来自 Roslyn 项目;它自 2007 年以来一直可用。然而,最近与 Roslyn 相关的体验得到了增强。另见visualstudiomagazine.com/articles/2014/02/26/…
【解决方案2】:

ArrayList实际上是在实现IList,应该比.Any()快。原因是因为它正在实现Count Property 而不是Count MethodCount Property 应该快速检查然后获取正确的属性。

看起来类似于:

ICollection<TSource> collection1 = source as ICollection<TSource>;

  if (collection1 != null)
    return collection1.Count;

  ICollection collection2 = source as ICollection;

  if (collection2 != null)
    return collection2.Count;

【讨论】:

    【解决方案3】:

    Marc Gravel 建议使用 Any() 而不是 Count()(扩展方法),但不一定要超过 Count(属性)。

    Count 属性总是会更快,因为它只是查找存储在堆上的 int。使用 linq 需要(相对)昂贵的对象分配来创建 IEnumerator,再加上 MoveNext 中的任何开销(如果列表不为空,则会在返回 true 之前将 ArrayList 的第一个成员的值不必要地复制到 Current 属性) .

    现在这对于性能来说都是微不足道的,但是执行它的代码更复杂,因此只有在具有令人信服的性能优势时才应该使用它。由于实际上存在微不足道的性能损失,我们应该选择更简单的代码。因此,我会将Any() 实现为return Count &gt; 0;

    但是,您的示例正在实现 Any 的参数化重载。在这种情况下,您的解决方案,委托给参数化 Any 扩展方法似乎是最好的。参数化的 Any 扩展方法和 Count 属性之间没有任何关系。

    【讨论】:

    • 在我的示例中,arraylist 已经被填充。所以谓词会做内存过滤。
    • @Yogendra 我想我明白了。我对您的第一个示例涉及 Count 属性而第二个示例涉及过滤的 Any 方法这一事实感到有些困惑。像您在示例中那样实现这一点具有封装 Cast 调用的优势,支持 DRY 原则 (en.wikipedia.org/wiki/Don't_repeat_yourself)。
    【解决方案4】:

    ArrayList 实现了IList,所以它确实有一个Count 属性。使用它会比Any() 更快,如果你只关心检查容器(非)空。

    【讨论】:

      猜你喜欢
      • 2013-08-16
      • 1970-01-01
      • 2014-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多