ArrayList计数与任意
本文关键字:任意 ArrayList | 更新日期: 2023-09-27 18:01:03
我正在研究一些遗留代码。该类使用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以获得计数?建议添加上面的"Any"方法吗。
Marc Gravel在下面的问题中建议使用Any作为IEnumerable
哪种方法性能更好:.Any((与.Count((>0?
.NET引用源表示ArrayList.Count返回一个缓存的私有变量。
为了完整起见,源代码还在这里列出了Any((扩展方法的实现。本质上,扩展方法执行null检查,然后尝试通过IEnumerable的枚举器获取第一个元素。
ArrayList
实际上是在实现IList
,它应该比.Any()
更快。原因是它实现的是Count Property
而不是Count Method
。Count 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;
Any()
而不是Count()
(扩展方法(,但不一定要使用Count
(属性(。
Count属性总是会更快,因为它只是在查找存储在堆上的int。使用linq需要(相对(昂贵的对象分配来创建IEnumerator,再加上MoveNext中的任何开销(如果列表不为空,那么在返回true之前,MoveNext将不必要地将ArrayList的第一个成员的值复制到Current属性(。
现在,这一切对于性能来说都是微不足道的,但执行这项操作的代码更为复杂,因此只有在具有显著性能优势的情况下才应该使用它。由于实际上存在微不足道的性能损失,我们应该选择更简单的代码。因此,我将把Any()
实现为return Count > 0;
。
但是,您的示例是实现Any的参数化重载。在这种情况下,您的解决方案,委派给参数化的Any扩展方法似乎是最好的。参数化的Any扩展方法和Count属性之间没有关系。
ArrayList
实现IList
,因此它确实具有Count
属性。如果您只关心检查容器(非(空,那么使用它将比Any()
更快。