使用集合,我有两种获取对象计数的方法:count(属性)和count()方法。有人知道什么是关键区别吗?我可能是错的,但我总是在任何条件语句中使用Count属性,因为我假设Count()方法对集合执行某种查询,其中As Count必须在我"获取"之前就已被分配。但这只是猜测-如果我错了,我不知道性能是否会受到影响。
编辑:出于好奇,那么,如果集合为空,count()是否会引发异常?因为我很确定Count属性只返回0。
- 两者都将为空集合抛出异常,因为它们都试图将.运算符应用于空的内容。
对Count()扩展方法的源代码进行反编译,可以测试对象是否是ICollection(泛型或其他)对象,如果是这样,只返回基础Count属性:
因此,如果您的代码访问Count,而不是调用Count(),那么您可以绕过类型检查——这是一个理论上的性能优势,但我怀疑它是否值得注意!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| // System.Linq.Enumerable
public static int Count <TSource >(this IEnumerable <TSource > source )
{
checked
{
if (source == null)
{
throw Error .ArgumentNull("source");
}
ICollection <TSource > collection = source as ICollection <TSource >;
if (collection != null)
{
return collection .Count;
}
ICollection collection2 = source as ICollection ;
if (collection2 != null)
{
return collection2 .Count;
}
int num = 0;
using (IEnumerator <TSource > enumerator = source .GetEnumerator())
{
while (enumerator .MoveNext())
{
num ++;
}
}
return num ;
}
} |
- 啊,对了,反正这只是一个进入房产的通道!"对象是否为ICollection"的评估将花费我所假设的时间。我知道,这些性能影响是微不足道的,不是我现在真正担心的事情,而是我刚刚好奇的事情。
- +1对于主动进行逆向工程,非常有帮助。
- 但是,请记住,在3.5中,Count()不检查非通用ICollection接口。这只是在.NET 4中添加的。3.5和4都检查通用ICollection接口。
- 对没有元素的序列调用Count将引发异常。但是count()可以工作。
- 伊恩,你能解释一下,如果我使用ICollection,每次更改集合时,此Count属性都会更改吗?添加/删除操作?
- @johnny_d-来自msdn文档-icocollection.count属性"获取icocollection中包含的元素数。"msdn.microsoft.com/en-us/library/&hellip;
- 这是否意味着,当我添加新项时,这个属性是递增的?或者是通过枚举计算出来的?
- @这取决于ICollection的具体实现。
绩效只是选择其中一个的原因。选择.count()意味着您的代码将更通用。我曾经重构过一些不再生成集合的代码,而是一些更通用的代码,比如IEnumerable,但是由于依赖于.Count,所以其他代码中断了,我不得不将其更改为.Count()。如果我指出在任何地方都使用.Count(),代码可能更易于重用和维护。通常选择使用更通用的接口,如果你能摆脱它是你最好的选择。我所说的更通用,是指由更多类型实现的更简单的接口,从而使代码之间的兼容性更强。
我不是说.Count()更好,我只是说还有其他一些考虑因素可以更好地处理您正在编写的代码的可重用性。
- +1对讨论有价值的补充。我正在维护的某些代码刚刚损坏,因为属性.count在htmlagilityPack的版本升级中无法生存。
- 那可能是双刃剑。如果有一天有人试图将IEnumerable修改为真正的生成器,该怎么办?在代码库中,我看到很多地方.count()假定可枚举的代码可以重复多次
- 真的。我认为,如果我们考虑开发人员的代码更改与框架代码更改,开发人员的代码更有可能会更改。如果在框架中做出这种改变,它将打破很多东西。传统上,它们在这些情况下引入新的集合/接口,以便开发人员可以根据需要进行迁移。
.Count()方法可能足够聪明,或者知道所讨论的类型,如果是这样,它可能使用基础.Count属性。
再说一遍,可能不会。
我想说,如果集合本身有一个.Count属性,那么在性能方面这将是您最好的选择。
如果.Count()方法不知道集合,它将枚举它,这将是一个O(N)操作。
- 使用Count属性可能会更好,但是使用ICollection.Count的Count()方法制作在这里有点记载:msdn.microsoft.com/en-us/library/bb338038(v=vs.110).aspx
count()方法是一个扩展方法,它迭代IEnumerable<>的每个元素,并返回有多少个元素。如果ienumerable的实例实际上是一个列表<>,那么最好返回count属性,而不是迭代所有元素。
- 即使我有一个列表<>,我也使用count()方法来保持代码更通用。当我重构类以在不需要特定集合实现的情况下使用IEnumerable<>时,这很好。
如果存在count或length属性,则应始终首选count()方法,该方法通常迭代整个集合以计算其中的元素数。(例外情况是,当count()方法针对linq to sql或linq to entities源时,例如,在这种情况下,它将对数据源执行count查询。即使这样,如果有Count属性,您也希望这样做,因为它可能要做的工作更少。)
短版本:如果在Count属性和Count()方法之间进行选择,则始终选择该属性。
差别主要在于操作的效率。公开Count属性的所有bcl集合都以o(1)的方式这样做。虽然Count()方法可以而且通常会花费O(n)。对于某些实现,有一些检查尝试将其传递给O(1),但这并不能保证。
count()方法是在任何IEnumerable<>上工作的Linq方法。您会期望count()方法在整个集合中迭代以查找count,但我相信linq代码实际上在其中有一些优化,以检测是否存在count属性,如果存在,则使用该属性。
所以他们都应该做几乎相同的事情。Count属性可能稍微好一点,因为不需要在其中进行类型检查。
Count()是linq-Count的一个扩展方法,它是List的一个属性,实际的.NET集合对象。
因此,Count()几乎总是较慢,因为它将枚举集合/可查询对象。在列表、队列、堆栈等中,使用Count。或者对于数组-Length。