我正在查看一些遗留代码。该类使用ArrayList来保留项目。这些项目从Database表中获取,最多可达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 for IEnumerable
答案 0 :(得分:4)
.NET reference source表示ArrayList.Count返回一个缓存的私有变量。
为了完整性,the source还列出了Any()扩展方法的实现。本质上,扩展方法执行空检查,然后尝试通过IEnumerable的枚举器获取第一个元素。
答案 1 :(得分:2)
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;
答案 2 :(得分:2)
Marc Gravel建议使用Any()
而非Count()
(扩展方法),但不一定超过Count
(属性)。
Count属性总是会更快,因为它只是查找存储在堆上的int。使用linq需要(相对)昂贵的对象分配来创建IEnumerator,加上MoveNext中的任何开销(如果列表不为空,将不必要地将ArrayList的第一个成员的值复制到Current属性)在返回真实之前)。
现在这对于性能来说非常简单,但是执行它的代码更复杂,所以只有在具有引人注目的性能优势时才应该使用它。由于这实际上是一个微不足道的性能损失,我们应该选择更简单的代码。因此,我会将Any()
实施为return Count > 0;
。
但是,您的示例是实现Any的参数化重载。在这种情况下,您的解决方案,委托参数化Any扩展方法似乎是最好的。参数化的Any扩展方法和Count属性之间没有任何关系。
答案 3 :(得分:1)
ArrayList
实现IList
,因此它具有Count
属性。使用它会比Any()
更快,如果你关心的是检查容器(非)空虚。