El orden de los métodos de extensión LINQ no afecta el rendimiento?

Me sorprende que, aparentemente, no importa si antepongo o anexo los métodos de extensión LINQ.

Probado con Enumerable.FirstOrDefault :

  1. hugeList.Where(x => x.Text.Contains("10000")).FirstOrDefault();
  2. hugeList.FirstOrDefault(x => x.Text.Contains("10000"));

     var hugeList = Enumerable.Range(1, 50000000) .Select(i => new { ID = i, Text = "Item" + i }); var sw1 = new System.Diagnostics.Stopwatch(); var sw2 = new System.Diagnostics.Stopwatch(); sw1.Start(); for(int i=0;i x.Text.Contains("10000")).FirstOrDefault(); sw1.Stop(); sw2.Start(); for(int i=0;i x.Text.Contains("10000")); sw2.Stop(); var result1 = String.Format("FirstOrDefault after: {0} FirstOrDefault before: {1}", sw1.Elapsed, sw2.Elapsed); //result1: FirstOrDefault after: 00:00:03.3169683 FirstOrDefault before: 00:00:03.0463219 sw2.Restart(); for (int i = 0; i  x.Text.Contains("10000")); sw2.Stop(); sw1.Restart(); for (int i = 0; i  x.Text.Contains("10000")).FirstOrDefault(); sw1.Stop(); var result2 = String.Format("FirstOrDefault before: {0} FirstOrDefault after: {1}", sw2.Elapsed, sw1.Elapsed); //result2: FirstOrDefault before: 00:00:03.6833079 FirstOrDefault after: 00:00:03.1675611 //average after:3.2422647 before: 3.3648149 (all seconds) 

Yo hubiera adivinado que sería más lento preceder a Where ya que debe encontrar todos los elementos coincidentes y luego tomar el primero y un FirstOrDefault precedido podría arrojar el primer elemento encontrado.

P: ¿Alguien puede explicar por qué estoy en el camino equivocado?

Yo hubiera adivinado que sería más lento preceder a Where ya que debe encontrar todos los elementos coincidentes y luego tomar el primero y un FirstOrDefault precedido podría arrojar el primer elemento encontrado. ¿Alguien puede explicar por qué estoy en el camino equivocado?

Estás en el camino equivocado porque tu primera afirmación es simplemente incorrecta. Where no se requiere encontrar todos los elementos coincidentes antes de ir a buscar el primer elemento coincidente. Where busca elementos coincidentes “a pedido”; si solo pide el primero, solo obtiene el primero. Si solo solicita las dos primeras, solo obtendrá las dos primeras.

Jon Skeet hace un buen papel en el escenario. Imagina que tienes tres personas La primera persona tiene un paquete de cartas barajadas. La segunda persona tiene una camiseta que dice “donde la tarjeta es roja”. La tercera persona golpea a la segunda persona y dice “dame la primera tarjeta”. La segunda persona golpea a la primera persona una y otra vez hasta que la primera persona entrega una tarjeta roja, que la segunda persona entrega a la tercera persona. La segunda persona no tiene motivos para seguir molestando a la primera persona; la tarea está hecha!

Ahora, si la camiseta de la segunda persona dice “orden por rango ascendente”, entonces tenemos una situación muy diferente. Ahora la segunda persona realmente necesita obtener cada carta de la primera persona, para encontrar la carta más baja en la baraja, antes de entregar la primera carta a la tercera persona.

Esto debería darle ahora la intuición necesaria para saber cuándo el orden importa por razones de rendimiento. El resultado neto de “darme las tarjetas rojas y luego ordenarlas” es exactamente lo mismo que “clasifica todas las cartas y luego dame las rojas”, pero la primera es mucho más rápida porque no tienes que pasar el tiempo ordenando el tarjetas negras que vas a descartar.

El método Where() usa la ejecución diferida y proporcionará el siguiente elemento coincidente según se solicite . Es decir, Where() no evalúa e inmediatamente devuelve una secuencia de todos los objetos candidatos, sino que los proporciona de a uno a medida que se repiten.

Como FirstOrDefault() detiene después del primer elemento, esto provocará que Where() deje de iterar.

Considere que FirstOrDefault() detiene la ejecución de Where() como si realizara un break . No es tan simple, por supuesto, pero en esencia ya que FirstOrDefault() deja de iterar una vez que encuentra un elemento, Where() no necesita continuar.

Por supuesto, esto es en el caso simple de aplicar una FirstOrDefault() en una cláusula Where() , si tiene otras cláusulas en las que implica la necesidad de considerar todos los elementos, esto podría tener un efecto, pero esto sería cierto tanto en utilizando Where().FirstOrDefault()' combo or just FirstOrDefault ()’ con un predicado.