在系统中。Linq命名空间,我们现在可以扩展我们的IEnumerable来拥有Any()和Count()扩展方法。
最近有人告诉我,如果我想检查一个集合中是否包含1个或多个项目,我应该使用. any()扩展方法而不是. count() > 0扩展方法,因为. count()扩展方法必须遍历所有项目。
其次,一些集合具有Count或Length属性(而不是扩展方法)。使用这些,而不是.Any()或.Count()会更好吗?
-是的-不?
在系统中。Linq命名空间,我们现在可以扩展我们的IEnumerable来拥有Any()和Count()扩展方法。
最近有人告诉我,如果我想检查一个集合中是否包含1个或多个项目,我应该使用. any()扩展方法而不是. count() > 0扩展方法,因为. count()扩展方法必须遍历所有项目。
其次,一些集合具有Count或Length属性(而不是扩展方法)。使用这些,而不是.Any()或.Count()会更好吗?
-是的-不?
当前回答
我已经使用IList创建了一个示例应用程序,其中包含100个元素到100万个项目,以查看Count vs Any哪个是最好的。
Code
class Program
{
static void Main()
{
//Creating List of customers
IList<Customer> customers = new List<Customer>();
for (int i = 0; i <= 100; i++)
{
Customer customer = new Customer
{
CustomerId = i,
CustomerName = string.Format("Customer{0}", i)
};
customers.Add(customer);
}
//Measuring time with count
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
if (customers.Count > 0)
{
Console.WriteLine("Customer list is not empty with count");
}
stopWatch.Stop();
Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
//Measuring time with any
stopWatch.Restart();
if (customers.Any())
{
Console.WriteLine("Customer list is not empty with any");
}
stopWatch.Stop();
Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
Console.ReadLine();
}
}
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
结果:
任何都比数好。
其他回答
你可以做一个简单的测试来弄清楚:
var query = //make any query here
var timeCount = new Stopwatch();
timeCount.Start();
if (query.Count > 0)
{
}
timeCount.Stop();
var testCount = timeCount.Elapsed;
var timeAny = new Stopwatch();
timeAny.Start();
if (query.Any())
{
}
timeAny.Stop();
var testAny = timeAny.Elapsed;
检查testCount和testAny的值。
如果您从具有. length或. count的东西开始(例如ICollection<T>, IList<T>, List<T>,等等),那么这将是最快的选项,因为它不需要通过Any()所要求的GetEnumerator()/MoveNext()/Dispose()序列来检查非空IEnumerable<T>序列。
对于IEnumerable<T>,则Any()通常会更快,因为它只需要查看一次迭代。但是,请注意Count()的LINQ-to-Objects实现确实检查ICollection<T>(使用.Count作为优化)-因此,如果您的底层数据源直接是一个列表/集合,则不会有很大的区别。不要问我为什么不使用非泛型的ICollection…
当然,如果你已经使用LINQ来过滤它(Where等),你将有一个基于迭代器块的序列,所以这个ICollection<T>优化是无用的。
通常,对于IEnumerable<T>:坚持使用Any();-p
这取决于数据集有多大,以及您的性能要求是什么?
如果不是很大,就用最易读的形式, 这对我来说是任何,因为它比方程更短更易读。
我已经使用IList创建了一个示例应用程序,其中包含100个元素到100万个项目,以查看Count vs Any哪个是最好的。
Code
class Program
{
static void Main()
{
//Creating List of customers
IList<Customer> customers = new List<Customer>();
for (int i = 0; i <= 100; i++)
{
Customer customer = new Customer
{
CustomerId = i,
CustomerName = string.Format("Customer{0}", i)
};
customers.Add(customer);
}
//Measuring time with count
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
if (customers.Count > 0)
{
Console.WriteLine("Customer list is not empty with count");
}
stopWatch.Stop();
Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
//Measuring time with any
stopWatch.Restart();
if (customers.Any())
{
Console.WriteLine("Customer list is not empty with any");
}
stopWatch.Stop();
Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
Console.ReadLine();
}
}
public class Customer
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
}
结果:
任何都比数好。
编辑:在EF 6.1.1版本中修复。这个答案是不实际的
对于SQL Server和EF4-6, Count()的执行速度比Any()快两倍。
当你运行Table.Any()时,它会生成类似这样的东西(警告:不要伤害大脑试图理解它)
SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [Table] AS [Extent1]
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT
1 AS [C1]
FROM [Table] AS [Extent2]
)) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
这需要对符合条件的行进行两次扫描。
我不喜欢写Count() > 0,因为它隐藏了我的意图。我更喜欢使用自定义谓词:
public static class QueryExtensions
{
public static bool Exists<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
return source.Count(predicate) > 0;
}
}