2010-09-22 14 views
6

ho avuto la seguente dichiarazione, che restituisce sempre null:Perché Null è una proiezione LINQ non valida?

var addins = allocations.SelectMany(
     set => set.locations.Any(q => q.IsMatch(level, count)) 
     ? (List<string>)set.addins : null 
    ); 

ho cambiato un po ', e ora funziona benissimo:

var addins = allocations.SelectMany(
     set => set.locations.Any(q => q.IsMatch(level, count)) 
     ? set.addins : new List<string>() 
    ); 

La mia domanda principale: perché non può servire come un nulla tipo di ritorno dall'operatore ternario in questo contesto di LINQ?

Una domanda secondaria: esiste un modo più intelligente per formulare la query precedente (in particolare se elimina la "nuova lista()")?

risposta

11

Enumerable.SelectMany tenterà di enumerare sulla sequenza restituita dal lambda, e getta un NullReferenceException cercando di chiamare GetEnumerator() su nulla. È necessario fornire una sequenza vuota effettiva. Invece di creare una nuova lista, è possibile utilizzare Enumerable.Empty:

var addins = allocations.SelectMany(
    set => set.locations.Any(q => q.IsMatch(level, count)) 
    ? (List<string>)set.addins : Enumerable.Empty<string>() 
    ); 

Ho il sospetto che quello che realmente vuole è quello di chiamare solo Dove prima SelectMany per filtrare i set non si vuole:

var addins = allocations 
    .Where(set => set.locations.Any(q => q.IsMatch(level, count))) 
    .SelectMany(set => (List<string>)set.addins); 

Oppure, nella sintassi della query:

var addins = 
    from set in allocations 
    where set.locations.Any(q => q.IsMatch(level, count)) 
    from addin in (List<string>)set.addins 
    select addin; 
+1

Risposta e approfondimenti eccellenti. Per inciso, il cast su "set.addins" non è necessario negli altri esempi, poiché l'operatore ternario non è coinvolto. –

1

fare quella:

(List<string>)set.addins : (List<string>)null

+0

L'avevo già provato. Non ha cambiato nulla. :( –

Problemi correlati