title: Is Linq to Objects chaining where clause VS && performance hit is that insignificant?
body: <p>following this question:<br>
   <a href="https://stackoverflow.com/questions/664683/should-i-use-two-where-clauses-or-in-my-linq-query?rq=1">Should I use two “where” clauses or “&amp;&amp;” in my LINQ query?</a><br>
  <a href="https://stackoverflow.com/questions/17210056/can-or-should-i-join-two-where-clauses-together-in-a-linq-query/17319779#17319779">Can or should I join two Where clauses together in a LINQ Query?</a><br>
  <a href="https://stackoverflow.com/questions/5188780/linq-styling-chaining-where-clause-vs-and-operator">linq styling, chaining where clause vs and operator</a><br>
  <a href="http://codeblog.jonskeet.uk/2011/06/16/linq-to-objects-and-the-performance-of-nested-quot-where-quot-calls/" rel="nofollow noreferrer">Jon Skeet: blog post</a> </p>
  
  <p>Most answers said that the <code>Linq To Objects</code> performance hit in chaining where clause vs &amp;&amp; in a single lambda expression is negligible so its up to your coding style to decide which one to use.</p>
  
  <p>I started by looking at IL assembly, you can definitely see that chaining where clause will result in  Where extension being called 2 times the and the input of the second call is the result of the first.</p>
  
  <pre><code>var numbers = new List&lt;int&gt;() { 1, 2 ,3,4,5,6,7,8,9,10};
  IEnumerable&lt;int&gt; query = numbers.Where(x=&gt; x&gt;2).Where(x =&gt; x&lt;5);
  </code></pre>
  
  <p>//The IL</p>
  
  <pre><code>IL_005B:  ldloc.0     // numbers
  IL_005C:  ldsfld      UserQuery.CS$&lt;&gt;9__CachedAnonymousMethodDelegate3
  IL_0061:  brtrue.s    IL_0076
  IL_0063:  ldnull      
  IL_0064:  ldftn       b__1
  IL_006A:  newobj      System.Func&lt;System.Int32,System.Boolean&gt;..ctor
  IL_006F:  stsfld      UserQuery.CS$&lt;&gt;9__CachedAnonymousMethodDelegate3
  IL_0074:  br.s        IL_0076
  IL_0076:  ldsfld      UserQuery.CS$&lt;&gt;9__CachedAnonymousMethodDelegate3
  IL_007B:  call        System.Linq.Enumerable.Where &lt;-----------First Call
  IL_0080:  ldsfld      UserQuery.CS$&lt;&gt;9__CachedAnonymousMethodDelegate4
  IL_0085:  brtrue.s    IL_009A
  IL_0087:  ldnull      
  IL_0088:  ldftn       b__2
  IL_008E:  newobj      System.Func&lt;System.Int32,System.Boolean&gt;..ctor
  IL_0093:  stsfld      UserQuery.CS$&lt;&gt;9__CachedAnonymousMethodDelegate4
  IL_0098:  br.s        IL_009A
  IL_009A:  ldsfld      UserQuery.CS$&lt;&gt;9__CachedAnonymousMethodDelegate4
  IL_009F:  call        System.Linq.Enumerable.Where &lt;------------Second Call
  IL_00A4:  stloc.1     // query
  b__1:
  IL_0000:  ldarg.0     
  IL_0001:  ldc.i4.2    
  IL_0002:  cgt         
  IL_0004:  stloc.0     // CS$1$0000
  IL_0005:  br.s        IL_0007
  IL_0007:  ldloc.0     // CS$1$0000
  IL_0008:  ret       
   b__2:
   IL_0000:  ldarg.0     
   IL_0001:  ldc.i4.5    
   IL_0002:  clt         
   IL_0004:  stloc.0     // CS$1$0000
   IL_0005:  br.s        IL_0007
   IL_0007:  ldloc.0     // CS$1$0000
   IL_0008:  ret    
  </code></pre>
  
  <p>Then I run a simple bench mark on Win7 .Net 3.5 and 4.0</p>
  
  <pre><code>  static void Main(string[] args)
  {               
      int size = 10000000;
      Console.WriteLine("chain clauses");
      RunTests(size,true);
  
      Console.WriteLine("use and");
      RunTests(size,false);               
  }
  
  
  static void RunTests(int size, bool chainClauses)
  {
      for (int i = 1; i &lt;= 10; i++)
       {
          if (chainClauses)
              RunTestChaining(i, size);
          else
              RunTestAnd(i, size);
          }
      }
  
      static void RunTestChaining(int depth, int size)
      {
          IEnumerable&lt;string&gt; input = Enumerable.Repeat("value", size);                      
  
          switch (depth)
          {
              case 1:
                  input = input.Where(x =&gt; !x.Equals("1"));
                  break;
              case 2:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2"));
                  break;
              case 3:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3"));
                  break;
              case 4:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4"));
                  break;
              case 5:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4")).Where(x =&gt; !x.Equals("5"));
                  break;
              case 6:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4")).Where(x =&gt; !x.Equals("5")).Where(x =&gt; !x.Equals("6"));
                  break;
              case 7:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4")).Where(x =&gt; !x.Equals("5")).Where(x =&gt; !x.Equals("6")).Where(x =&gt; !x.Equals("7"));
                  break;
              case 8:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4")).Where(x =&gt; !x.Equals("5")).Where(x =&gt; !x.Equals("6")).Where(x =&gt; !x.Equals("7")).Where(x =&gt; !x.Equals("8"));
                  break;
              case 9:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4")).Where(x =&gt; !x.Equals("5")).Where(x =&gt; !x.Equals("6")).Where(x =&gt; !x.Equals("7")).Where(x =&gt; !x.Equals("8")).Where(x =&gt; !x.Equals("9"));
                  break;
              case 10:
                  input = input.Where(x =&gt; !x.Equals("1")).Where(x =&gt; !x.Equals("2")).Where(x =&gt; !x.Equals("3")).Where(x =&gt; !x.Equals("4")).Where(x =&gt; !x.Equals("5")).Where(x =&gt; !x.Equals("6")).Where(x =&gt; !x.Equals("7")).Where(x =&gt; !x.Equals("8")).Where(x =&gt; !x.Equals("9")).Where(x =&gt; !x.Equals("10"));
                  break;
          }
  
          Stopwatch sw = Stopwatch.StartNew();
          var count = input.Count();
          sw.Stop();
          Console.WriteLine("Depth: {0} Count: {1} Time: {2}ms",
                            depth, count, sw.ElapsedMilliseconds);
      }
  
  static void RunTestAnd(int depth, int size )
      {
          IEnumerable&lt;string&gt; input = Enumerable.Repeat("value", size);
          Func&lt;string, bool&gt; predicate = x =&gt; true;
          switch (depth)
          {
              case 1:
                  predicate = x =&gt; !x.Equals("1");
                  break;
              case 2:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2");
                  break;
              case 3:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3");
                  break;
              case 4:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3");
                  break;
              case 5:
                   predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3")&amp;&amp; !x.Equals("5");
                  break;
              case 6:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3")&amp;&amp; !x.Equals("5") &amp;&amp; !x.Equals("6");
                  break;
              case 7:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3")&amp;&amp; !x.Equals("5") &amp;&amp; !x.Equals("6") &amp;&amp; !x.Equals("7");
                  break;
              case 8:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3")&amp;&amp; !x.Equals("5") &amp;&amp; !x.Equals("6") &amp;&amp; !x.Equals("7") &amp;&amp; !x.Equals("8");
                  break;
              case 9:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3")&amp;&amp; !x.Equals("5") &amp;&amp; !x.Equals("6") &amp;&amp; !x.Equals("7") &amp;&amp; !x.Equals("8") &amp;&amp; !x.Equals("9");
                  break;
              case 10:
                  predicate = x =&gt; !x.Equals("1") &amp;&amp; !x.Equals("2") &amp;&amp; !x.Equals("3")&amp;&amp;!x.Equals("3")&amp;&amp; !x.Equals("5") &amp;&amp; !x.Equals("6") &amp;&amp; !x.Equals("7") &amp;&amp; !x.Equals("8") &amp;&amp; !x.Equals("9") &amp;&amp; !x.Equals("10");
                  break;
          }
          input = input.Where(predicate);
  
          Stopwatch sw = Stopwatch.StartNew();
          var count = input.Count();
          sw.Stop();
          Console.WriteLine("Depth: {0} Count: {1} Time: {2}ms",
                            depth, count, sw.ElapsedMilliseconds);
      } 
  </code></pre>
  
  <p>And the results:</p>
  
  <pre><code>// .Net 3.5                                //.Net 4.0
  chain clauses                               chain clauses
  Depth: 1 Count: 10000000 Time: 181ms        Depth: 1 Count: 10000000 Time: 216ms
  Depth: 2 Count: 10000000 Time: 248ms        Depth: 2 Count: 10000000 Time: 278ms
  Depth: 3 Count: 10000000 Time: 315ms        Depth: 3 Count: 10000000 Time: 347ms
  Depth: 4 Count: 10000000 Time: 378ms        Depth: 4 Count: 10000000 Time: 437ms
  Depth: 5 Count: 10000000 Time: 443ms        Depth: 5 Count: 10000000 Time: 509ms
  Depth: 6 Count: 10000000 Time: 514ms        Depth: 6 Count: 10000000 Time: 573ms
  Depth: 7 Count: 10000000 Time: 579ms        Depth: 7 Count: 10000000 Time: 649ms
  Depth: 8 Count: 10000000 Time: 644ms        Depth: 8 Count: 10000000 Time: 727ms
  Depth: 9 Count: 10000000 Time: 978ms        Depth: 9 Count: 10000000 Time: 1278ms
  Depth: 10 Count: 10000000 Time: 1546ms      Depth: 10 Count: 10000000 Time: 1075ms
  use and                                     use and
  Depth: 1 Count: 10000000 Time: 181ms        Depth: 1 Count: 10000000 Time: 202ms
  Depth: 2 Count: 10000000 Time: 200ms        Depth: 2 Count: 10000000 Time: 234ms
  Depth: 3 Count: 10000000 Time: 228ms        Depth: 3 Count: 10000000 Time: 267ms
  Depth: 4 Count: 10000000 Time: 245ms        Depth: 4 Count: 10000000 Time: 303ms
  Depth: 5 Count: 10000000 Time: 267ms        Depth: 5 Count: 10000000 Time: 335ms
  Depth: 6 Count: 10000000 Time: 289ms        Depth: 6 Count: 10000000 Time: 364ms
  Depth: 7 Count: 10000000 Time: 312ms        Depth: 7 Count: 10000000 Time: 397ms
  Depth: 8 Count: 10000000 Time: 326ms        Depth: 8 Count: 10000000 Time: 432ms
  Depth: 9 Count: 10000000 Time: 366ms        Depth: 9 Count: 10000000 Time: 462ms
  Depth: 10 Count: 10000000 Time: 375ms       Depth: 10 Count: 10000000 Time: 493ms
  </code></pre>
  
  <p>According to these results there is a significant performance deterioration, which points to a conclusion that you should avoid chaining where clause in Linq to Objects.<br>
  Or There Is something I am missing?</p>