在系统中。Linq命名空间,我们现在可以扩展我们的IEnumerable来拥有Any()和Count()扩展方法。

最近有人告诉我,如果我想检查一个集合中是否包含1个或多个项目,我应该使用. any()扩展方法而不是. count() > 0扩展方法,因为. count()扩展方法必须遍历所有项目。

其次,一些集合具有Count或Length属性(而不是扩展方法)。使用这些,而不是.Any()或.Count()会更好吗?

-是的-不?


当前回答

由于这是一个相当流行的话题,答案各不相同,我不得不重新审视这个问题。

测试env: EF 6.1.3, SQL Server, 300k记录

表模型:

class TestTable
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }
}

测试代码:

class Program
{
    static void Main()
    {
        using (var context = new TestContext())
        {
            context.Database.Log = Console.WriteLine;

            context.TestTables.Where(x => x.Surname.Contains("Surname")).Any(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Any(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname")).Count(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Count(x => x.Id > 1000);

            Console.ReadLine();
        }
    }
}

结果:

Any() ~ 3ms

Count()第一次查询~ 230ms,第二次查询~ 400ms

备注:

对于我的案例,EF没有像@Ben在他的帖子中提到的那样生成SQL。

其他回答

关于Count()方法,如果IEnumerable是一个ICollection,那么我们不能遍历所有的项目,因为我们可以检索ICollection的Count字段,如果IEnumerable不是一个ICollection,我们必须使用一个MoveNext while遍历所有的项目,看看。net框架代码:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) 
        throw Error.ArgumentNull("source");

    ICollection<TSource> collectionoft = source as ICollection<TSource>;
    if (collectionoft != null) 
        return collectionoft.Count;

    ICollection collection = source as ICollection;
    if (collection != null) 
        return collection.Count;

    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        checked
        {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}

参考:可枚举的参考源

你可以做一个简单的测试来弄清楚:

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的值。

由于这是一个相当流行的话题,答案各不相同,我不得不重新审视这个问题。

测试env: EF 6.1.3, SQL Server, 300k记录

表模型:

class TestTable
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }
}

测试代码:

class Program
{
    static void Main()
    {
        using (var context = new TestContext())
        {
            context.Database.Log = Console.WriteLine;

            context.TestTables.Where(x => x.Surname.Contains("Surname")).Any(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Any(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname")).Count(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Count(x => x.Id > 1000);

            Console.ReadLine();
        }
    }
}

结果:

Any() ~ 3ms

Count()第一次查询~ 230ms,第二次查询~ 400ms

备注:

对于我的案例,EF没有像@Ben在他的帖子中提到的那样生成SQL。

这取决于数据集有多大,以及您的性能要求是什么?

如果不是很大,就用最易读的形式, 这对我来说是任何,因为它比方程更短更易读。

我已经使用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; }
}

结果:

任何都比数好。