Wednesday, April 6, 2011

Common LINQ mistakes

  1. Never use
    enumerable.Count() > 0

    Instead use
    enumerable.Any()

    Count() will enumerate entire collection, Any() will stop after first item.
  2. Never ever use
    from x in enumerable
    orderby x.Item1
    orderby x.Item2
    select x;
    
    Your collection will be ordered by x.Item2, not by x.Item1 then by x.Item2. Instead use:
    from x in enumerable
    orderby x.Item1, x.Item2
    select x;
    
    The same is applicable for extensions methods.
    Wrong:
    var ordered = enumerable.OrderBy(x=>x.Item1).OrderBy(x=>x.Item2);
    
    Correct:
    var ordered = enumerable.OrderBy(x=>x.Item1).ThenBy(x=>x.Item2);
    
  3. Do not forget about closures scope.
    foreach (var x in enumerable)
    {
     var some = enumerable2.Where(y => y == x);
     list.Add(some);
    }
    
    As far as x is closed, you probably assume that 'some' will depend on each item from 'enumerable'. But actually, 'x' is defined outside of foreach (due to C# implementation), so all 'some's will be calculated using the last value. To prevent this, either fold all enumerables (in general - all lazy calculations) inside blocks, or use locally scoped variables.
    foreach (var x in enumerable)
    {
     var local = x; 
     var some = enumerable2.Where(y => y == local);
     list.Add(some);
    }
    
    Fortunately, Resharper will not let you forget about this.

1 comment: