2013-03-20 19 views
18

Ho la seguente query LINQ che genera ed eccezione quando FirstOrDefault() restituisce null. Idealmente vorrei evitare il controllo nulla. C'è un modo per fare questo? Desidero restituire 0 se non ci sono CPOffsets che soddisfano la chiamata FirstOrDefault().LINQ - FirstOrDefault() quindi Select()

double offset = OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime).CPOffset; 

L'unico modo che posso vedere per raggiungere questo obiettivo è la seguente:

CPOffset cpOffset = OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime); 
double offset = cpOffset != null ? cpOffset.CPOffset : 0; 

C'è un altro modo più succinto? Utilizzare Select() dopo che lo FirstorDefault() non viene compilato ma ho pensato che potrebbe essere appropriato qui?

+1

Questo è davvero così succinto come si sta per ottenere ... il più delle volte "abbastanza buono" è abbastanza buono :-) – theMayer

+0

Sono d'accordo. Se lo vuoi _more_ succinto, probabilmente dovrai eseguire il tuo metodo o il tuo metodo di estensione. (che non è necessariamente una cosa negativa) EDIT: Niente di male con 'double offset = DetermineOffset (OrderedOffsets, cpTime);' or 'double offset = OrderedOffsets.DetermineOffset (cpTime)' o 'double offset = OrderedOffsets.DetermineOffset (o = > o.OffsetDateTime> cpTime); 'se vuoi un po 'più di controllo sul predicato. –

+0

Controlla questo: http: //stackoverflow.com/questions/14791514/streamlined-way-to-do-c-sharp-run-time-type-identification-that-avoids-a-null-ch/14791613#14791613 –

risposta

34

penso che questo dovrebbe funzionare, io non sono vicino VS di check it out ...

OrderedOffsets.Where(o => o.OffsetDateTime > cpTime).Select(x => x.CPOffset).FirstOrDefault(); 
+1

@Servy: sarebbe vero se tutti gli OffsetDateTime sono Simon

+0

@Servy, supponiamo che 'First' sarebbe sufficiente. Quanto sarebbe meglio dell'uso di 'FirstOrDefault'? 9 caratteri? – I4V

+0

Lenta, ho scritto una propria soluzione per questo che non sta iterando attraverso la raccolta completa (questo è ciò che fa con dove). –

9

DefaultIfEmpty può essere utilizzato per garantire che la raccolta ha sempre almeno un elemento.

double offset = OrderedOffsets.Where(o => o.OffsetDateTime > cpTime) 
    .Select(o => o.CPOffset) 
    .DefaultIfEmpty() 
    .First(); 
2

Penso che un buon motivo potrebbe essere:

double offset = (OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime) ?? someDefaultObject).CPOffset; 

con someDefaultObject un oggetto che contiene i valori di default ... Con questo modello, è possibile modificare facilmente i valori di default tramite il codice!

Se OrderedOffsets può essere una struttura, è possibile anche inserire qui il valore predefinito! :)

+1

OK, funzionerebbe, ma, perché pensi che sarebbe meglio della risposta di NSGaga. Non richiede un oggetto temporaneo 'someDefaultObject' e più leggibile (ovviamente soggettivo) –

+0

sì, ma non mi piace che conserviamo tutti i valori> cpTime dopo' Dove' preferisco un metodo che ritorna dopo averlo trovato il primo elemento, e se la lista fosse megahuge, vogliamo davvero proiettare tutti i CPOffset che passano in una nuova forma? Penso che non valga la pena di salvare una linea ... Preferirei andare per le due linee inizialmente nella domanda ... – Romain

+1

Penso che dovresti leggere di più su Linq e sulla valutazione pigra. La risposta di NSGaga tornerà non appena trova la prima partita. Farebbe scorrere tutta la lista se non trova una corrispondenza valida anche per la tua risposta. –

Problemi correlati