Según tengo entendido, en Linq el método FirstOrDefault()
puede devolver un Default
valor de algo distinto de nulo. Lo que no he resuelto es qué tipo de cosas que no sean nulas pueden ser devueltas por este método (y similar) cuando no hay elementos en el resultado de la consulta. ¿Hay alguna forma particular de que esto se pueda configurar para que, si no hay un valor para una consulta en particular, se devuelva algún valor predefinido como valor predeterminado?
142
YourCollection.FirstOrDefault()
, podría usar,YourCollection.DefaultIfEmpty(YourDefault).First()
por ejemplo.MyCollection.Last().GetValueOrDefault(0)
para eso. De lo contrario, la respuesta de @Jon Skeet a continuación es IMO correcta.Respuestas:
Caso general, no solo para los tipos de valor:
De nuevo, esto no se puede decir si hay era algo en su secuencia, o si el primer valor es el valor predeterminado.
Si te importa esto, podrías hacer algo como
y usar como
aunque, como señala el Sr. Steak, esto podría hacerse igual de bien
.DefaultIfEmpty(...).First()
.fuente
<T>
en sus nombres, pero lo más grave es quevalue == default(T)
no funciona (porque quién sabe siT
puede ser comparado por la igualdad?)EqualityComparer<T>.Default.Equals(value, default(T))
para evitar el boxeo y evitar una excepción si el valor esnull
No. O, más bien, siempre devuelve el valor predeterminado para el tipo de elemento ... que es una referencia nula, el valor nulo de un tipo de valor anulable o el valor natural "todos ceros" para un tipo de valor no anulable.
Para los tipos de referencia, solo puede usar:
Por supuesto, esto también le dará el "otro valor predeterminado" si el primer valor está presente, pero es una referencia nula ...
fuente
int
. Me gusta mucho más el uso deDefaultIfEmpty
:src.Where(filter).DefaultIfEmpty(defaultValue).First()
. Funciona tanto para el tipo de valor como para el tipo de referencia.Puede usar DefaultIfEmpty seguido de Primero :
fuente
DefaultIfEmpty
- que funciona con las API de todo lo que necesitan un defecto se debe especificar:First()
,Last()
, etc. Como usuario, usted no necesita recordar qué API permite especificar por defecto que no lo hacen. ¡Muy elegante!De la documentación para FirstOrDefault
De la documentación por defecto (T) :
Por lo tanto, el valor predeterminado puede ser nulo o 0 dependiendo de si el tipo es una referencia o un tipo de valor, pero no puede controlar el comportamiento predeterminado.
fuente
Copiado del comentario de @sloth
En lugar de
YourCollection.FirstOrDefault()
, podría usar,YourCollection.DefaultIfEmpty(YourDefault).First()
por ejemplo.Ejemplo:
fuente
DefaultIfEmpty
devuelve el valor predeterminado SI la colección está vacía (tiene 0 elementos). Si usaFirst
WITH con una expresión coincidente como en su ejemplo y esa condición no encuentra ningún artículo, su valor de retorno estará vacío.También puedes hacer esto
Esto usa solo linq - yipee!
fuente
FirstOrDefault
lugar deFirst
. De acuerdo con msdn.microsoft.com/en-us/library/bb340482.aspx , el uso recomendado esFirst
En realidad, uso dos enfoques para evitar
NullReferenceException
cuando estoy trabajando con colecciones:Para C # 6.0 o posterior:
Use
?.
o?[
para probar si es nulo antes de realizar un acceso de miembro Documentación de operadores condicional nuloEjemplo:
var barCSharp6 = list.FirstOrDefault()?.Bar;
C # versión anterior:
Úselo
DefaultIfEmpty()
para recuperar un valor predeterminado si la secuencia está vacía. Documentación de MSDNEjemplo:
string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
fuente
En lugar de
YourCollection.FirstOrDefault()
, podría usar,YourCollection.DefaultIfEmpty(YourDefault).First()
por ejemplo.fuente
Acabo de tener una situación similar y estaba buscando una solución que me permitiera devolver un valor predeterminado alternativo sin ocuparme de él cada vez que lo necesito. Lo que solemos hacer en caso de que Linq no admita lo que queremos es escribir una nueva extensión que se encargue de ello. Eso fue lo que hice. Esto es lo que se me ocurrió (aunque no probado):
fuente
Sé que ha pasado un tiempo, pero agregaré a esto, basado en la respuesta más popular, pero con una pequeña extensión, me gustaría compartir lo siguiente:
Esto me permite llamarlo en línea como tal con mi propio ejemplo con el que estaba teniendo problemas:
Entonces, para mí, solo quería que un resolutor predeterminado se usara en línea, puedo hacer mi verificación habitual y luego pasar una función para que no se instancia una clase, incluso si no se usa, ¡es una función para ejecutar cuando sea necesario!
fuente
Usar en
DefaultIfEmpty()
lugar deFirstOrDefault()
.fuente