LINQ: Cuándo utilizar SingleOrDefault frente a FirstOrDefault() con criterios de filtrado

Resuelto p.campbell asked hace 14 años • 17 respuestas

Considere los métodos de extensión IEnumerable SingleOrDefault()yFirstOrDefault()

MSDN documenta queSingleOrDefault :

Devuelve el único elemento de una secuencia, o un valor predeterminado si la secuencia está vacía; este método genera una excepción si hay más de un elemento en la secuencia.

mientras que FirstOrDefaultdesde MSDN (presumiblemente cuando se usa OrderBy()o OrderByDescending()ninguno),

Devuelve el primer elemento de una secuencia.

Considere un puñado de consultas de ejemplo; no siempre está claro cuándo utilizar estos dos métodos:

var someCust = db.Customers
.SingleOrDefault(c=>c.ID == 5); //unlikely(?) to be more than one, but technically COULD BE

var bobbyCust = db.Customers
.FirstOrDefault(c=>c.FirstName == "Bobby"); //clearly could be one or many, so use First?

var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or does it matter?

Pregunta

¿Qué convenciones sigue o sugiere al decidir utilizar SingleOrDefault()y FirstOrDefault()en sus consultas LINQ?

p.campbell avatar Nov 17 '09 06:11 p.campbell
Aceptado

Si su conjunto de resultados devuelve 0 registros:

  • SingleOrDefaultdevuelve el valor predeterminado para el tipo (por ejemplo, el valor predeterminado para int es 0)
  • FirstOrDefaultdevuelve el valor predeterminado para el tipo

Si su conjunto de resultados devuelve 1 registro:

  • SingleOrDefaultdevuelve ese registro
  • FirstOrDefaultdevuelve ese registro

Si su conjunto de resultados devuelve muchos registros:

  • SingleOrDefaultlanza una excepción
  • FirstOrDefaultdevuelve el primer registro

Conclusión:

Si desea que se produzca una excepción si el conjunto de resultados contiene muchos registros, utilice SingleOrDefault.

Si siempre desea 1 registro sin importar lo que contenga el conjunto de resultados, useFirstOrDefault

Alex avatar Jan 21 '2011 14:01 Alex

Siempre que utilice SingleOrDefault, indique claramente que la consulta debe generar como máximo un resultado único . Por otro lado, cuando FirstOrDefaultse usa, la consulta puede devolver cualquier cantidad de resultados, pero usted indica que solo desea el primero.

Personalmente encuentro que la semántica es muy diferente y usar la adecuada, dependiendo de los resultados esperados, mejora la legibilidad.

Bryan Menard avatar Nov 17 '2009 00:11 Bryan Menard

Hay

  • una diferencia semántica
  • una diferencia de rendimiento

entre los dos.

Diferencia semántica:

  • FirstOrDefaultdevuelve un primer elemento potencialmente múltiple (o predeterminado si no existe ninguno).
  • SingleOrDefaultasume que hay un solo artículo y lo devuelve (o lo devuelve por defecto si no existe ninguno). Varios elementos constituyen una violación del contrato, se lanza una excepción.

Diferencia de rendimiento

  • FirstOrDefaultsuele ser más rápido, itera hasta que encuentra el elemento y solo tiene que iterar todo el enumerable cuando no lo encuentra. En muchos casos, existe una alta probabilidad de encontrar un artículo.

  • SingleOrDefaultnecesita verificar si solo hay un elemento y, por lo tanto, siempre itera todo el enumerable. En teoría, podría dejar de iterar cuando encuentre un segundo elemento y generar una excepción. Pero en la mayoría de los casos no existe un segundo elemento, por lo que no ayuda mucho.

Conclusión

  • Úselo FirstOrDefaultsi no le importa cuántos elementos hay o cuando no puede permitirse el lujo de verificar la unicidad (por ejemplo, en una colección muy grande). Cuando verifica la singularidad al agregar elementos a la colección, puede resultar demasiado costoso verificarlo nuevamente al buscar esos elementos.

  • Úselo SingleOrDefaultsi no tiene que preocuparse demasiado por el rendimiento y desea asegurarse de que la suposición de un solo elemento sea clara para el lector y se verifique en tiempo de ejecución.

En la práctica, se utiliza First/ FirstOrDefaulta menudo incluso en los casos en los que se asume un solo elemento, para mejorar el rendimiento. Aún debes recordar que Single/ SingleOrDefaultpuede mejorar la legibilidad (porque establece la suposición de un solo elemento) y la estabilidad (porque lo verifica) y usarlo apropiadamente.

Stefan Steinegger avatar Nov 17 '2009 00:11 Stefan Steinegger