Aquí hay una versión simplificada de lo que estoy tratando de hacer:
var days = new Dictionary<int, string>();
days.Add(1, "Monday");
days.Add(2, "Tuesday");
...
days.Add(7, "Sunday");
var sampleText = "My favorite day of the week is 'xyz'";
var day = days.FirstOrDefault(x => sampleText.Contains(x.Value));
Dado que 'xyz' no está presente en el diccionario, el método FirstOrDefault no devolverá un valor válido. Quiero poder verificar esta situación, pero me doy cuenta de que no puedo comparar el resultado con "nulo" porque KeyValuePair es una estructura. El siguiente código no es válido:
if (day == null) {
System.Diagnotics.Debug.Write("Couldn't find day of week");
}
Si intenta compilar el código, Visual Studio arroja el siguiente error:
Operator '==' cannot be applied to operands of type 'System.Collections.Generic.KeyValuePair<int,string>' and '<null>'
¿Cómo puedo comprobar que FirstOrDefault ha devuelto un valor válido?
Respuestas:
FirstOrDefault
no devuelve nulo, devuelvedefault(T)
.Debes buscar:
Desde MSDN -
Enumerable.FirstOrDefault<TSource>
:Notas:
EqualityComparer<T>.Default.Equals(day, defaultDay)
, porque.Equals
puede ser anulado oday
podría ser unnull
.KeyValuePair<int, string> defaultDay = default;
, consulte Literal "predeterminado" con tipo de destino .FirstOrDefault
fuente
typeof
? Este código se compila y funciona.default(KeyValuePair<T1, T2>)
que resultaría. Ok, debería haber sido bastante obvio, que resultaría en un KVP vacío. Pero como "ser obvio" no es un buen enfoque para escribir aplicaciones adecuadas (y mi implementación actual es demasiado compleja para provocar este caso de manera clara / limpia), lo probé con un nuevo proyecto y, de hecho, devolvió unKeyValuePair
con propiedadesKey
yValue
siendo ambosNULL
.... solo para salvar a otras personas estos 5 minutos de estupidez ;-)default
palabra clave, claramente falta aquí. ¡Gracias!KeyValuePair
. Si tuviera un código genérico,day.Equals
ni siquiera es seguro para nulos, y lo habría usadoEqualityComparer<T>.Default.Equals(day, defaultDay)
Esta es la forma más clara y concisa en mi opinión:
Esto evita por completo el uso de extraños valores predeterminados para estructuras.
fuente
days
es unDictionary<int,string>
. Por lo tanto, será considerado como unaIEnumerable<KeyValuePair<int,string>>
, entonces se comporta como se espera cuandoAny()
yFirst()
son llamados. Supongo que hay otras implementaciones que pueden comportarse de manera diferente comoIEnumerable<>
. No sé si me estoy perdiendo algo.Puedes hacer esto en su lugar:
y entonces :
fuente