LINQ performance Count vs Where and Count

前端 未结 6 2007
礼貌的吻别
礼貌的吻别 2020-12-08 10:14
public class Group
{
   public string Name { get; set; }
}  

Test:

List _groups = new List();

for (i         


        
6条回答
  •  庸人自扰
    2020-12-08 10:32

    It looks to me that the difference is in how the Linq extensions are coded. I suspect Where is using optimizations in the List<> class to speed up the operations, but Count just iterates through an IEnumerable<>.

    If you do the same process, but with an IEnumerable, both methods are close, with Where being slightly slower.

    List _groups = new List();
    
    for (int i = 0; i < 10000; i++)
    {
        var group = new Group();
    
        group.Name = i + "asdasdasd";
        _groups.Add(group);
    }
    
    IEnumerable _groupsEnumerable = from g in _groups select g;
    
    Stopwatch _stopwatch2 = new Stopwatch();
    
    _stopwatch2.Start();
    foreach (var group in _groups)
    {
        var count = _groupsEnumerable.Count(x => x.Name == group.Name);
    }
    _stopwatch2.Stop();
    
    Console.WriteLine(_stopwatch2.ElapsedMilliseconds);
    Stopwatch _stopwatch = new Stopwatch();
    
    _stopwatch.Start();
    foreach (var group in _groups)
    {
        var count = _groupsEnumerable.Where(x => x.Name == group.Name).Count();
    }
    _stopwatch.Stop();
    
    Console.WriteLine(_stopwatch.ElapsedMilliseconds);
    

    Where extension method. Notice the if (source is List) case:

    public static IEnumerable Where(this IEnumerable source, Func predicate)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        if (predicate == null)
        {
            throw Error.ArgumentNull("predicate");
        }
        if (source is Enumerable.Iterator)
        {
            return ((Enumerable.Iterator)source).Where(predicate);
        }
        if (source is TSource[])
        {
            return new Enumerable.WhereArrayIterator((TSource[])source, predicate);
        }
        if (source is List)
        {
            return new Enumerable.WhereListIterator((List)source, predicate);
        }
        return new Enumerable.WhereEnumerableIterator(source, predicate);
    }
    

    Count method. Just iterates through the IEnumerable:

    public static int Count(this IEnumerable source, Func predicate)
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        if (predicate == null)
        {
            throw Error.ArgumentNull("predicate");
        }
        int num = 0;
        checked
        {
            foreach (TSource current in source)
            {
                if (predicate(current))
                {
                    num++;
                }
            }
            return num;
        }
    }
    

提交回复
热议问题