2012-03-24 17 views
26

Tengo la siguiente consulta LINQ:¿Cómo se manejan los nulos en LINQ cuando se usa Min o Max?

result.Partials.Where(o => o.IsPositive).Min(o => o.Result) 

consigo una excepción cuando result.Partials.Where (o => o.IsPositive) no contiene elementos. ¿Hay una manera elegante de manejar esto aparte de dividir la operación en dos y verificar nulo? Tengo una clase llena de operaciones como esta.

EDITAR: La pregunta está relacionada con LINQ to Objects.

Esta es la excepción que estoy recibiendo (traducido dice: La secuencia está vacía):

enter image description here

+0

¿Qué excepción obtienes? En mi experiencia, si 'Partials' está vacío, deberías obtener 0. –

+0

tu rastro de pila tiene una llamada a' Min() 'not' Sum() '. ¿Qué es 'resultado'? – Jon

+0

Lo siento. Mi mal, la operación es Min y Max, no suma. Lo siento de nuevo. Editando la pregunta. –

Respuesta

53

Un breve resumen de el cálculo de un Min

var min = result.Partials.Where(o => o.IsPositive).Min(o => o.Result); 

Ésta es su caso: si no hay elementos que coinciden, entonces la llamada Min lanzará una excepción (InvalidOperationException).

var min = result.Partials.Where(o => o.IsPositive) 
          .Select(o => o.Result) 
          .DefaultIfEmpty().Min(); 

DefaultIfEmpty creará una enumeración sobre el elemento 0, cuando no hay elementos en la lista. ¿Cómo sabes que 0 es el Min o 0 representa una lista sin elementos?

var min = result.Partials.Where(o => o.IsPositive) 
          .Min(o => (decimal?)o.Result); 

Aquí min es o bien nulo (defaul(decimal?)) o la actual Min encontró. Entonces un consumidor de este resultado sabrá que si el resultado es nulo, entonces la lista no tiene elementos y cuando el resultado es un valor de decimal, entonces la lista tiene algunos elementos y el Min de esos elementos es ese valor.

Sin embargo, cuando esto no importe, se puede llamar a min.GetValueOrDefault(0).

6

No se puede utilizar Min (o Max) si la secuencia está vacía. Si eso no debería suceder, tiene un problema diferente con la forma en que define result. De lo contrario, se debe comprobar si la secuencia está vacía y manejar apropiadamente, por ejemplo:

var query = result.Partials.Where(o => o.IsPositve); 
min = query.Any() ? query.Min(o => o.Result) : 0; // insert a different "default" value of your choice...  
+0

esto hará 2 consultas. pero se puede hacer con uno. – maxlego

8

Usted puede utilizar el método DefaultIfEmpty para garantizar la recogida tiene por lo menos 1 punto:

result.Partials.Where(o => o.IsPositive).Select(o => o.Result).DefaultIfEmpty().Min(); 
+0

... ¿qué ocurre si el valor predeterminado es nulo? –

+0

@RitchMelton: creo que Min devolverá nulo. –

+0

Estoy bastante seguro de que al invocar 'o.Result' con un elemento nulo se produce una excepción. –

Cuestiones relacionadas