2010-05-17 5 views
14

Ho un sacco di stringhe che ho bisogno di usare. Trim(), ma possono essere nulle. Sarebbe molto più conciso se potessi fare qualcosa di simile:Negate l'operatore con coalizione nulla

string endString = startString !?? startString.Trim(); 

tornare Fondamentalmente la parte a destra se la parte a sinistra non è nullo, altrimenti solo restituisce il valore null. Ho appena finito di usare l'operatore ternario, ma è comunque necessario utilizzare l'operatore a coalescenza nulla per questo scopo?

+3

Non penso, tbh cosa c'è di sbagliato in '! String.IsNullOrEmpty (startString)? startString.Trim(): null; ' – flq

+1

Come ho capito la tua domanda, vuoi propagare null ie se la stringa è nullo, restituire null. Altrimenti, riaccendere la corda tagliata. È corretto? Se questo è il caso, non c'è un operatore o un metodo integrato per farlo. Puoi usare un operatore ternario (come hai fatto) o scrivere un metodo. –

+0

Sto ancora aspettando che questo operatore faccia parte della lingua :( – PedroC88

risposta

12

È potrebbe creare un metodo di estensione che restituisce null quando tenta di tagliare il valore.

public String TrimIfNotNull(this string item) 
{ 
    if(String.IsNullOrEmpty(item)) 
    return item; 
    else 
    return item.Trim(); 
} 

Nota: non è possibile denominarlo Trim perché i metodi di estensione non possono sovrascrivere i metodi di istanza.

+0

Sembra così sbagliato che funzioni quando 'item' è nullo ... Ma, ho confermato che funziona. 'string s = null; s.TrimIfNotNull(); 'No' NullReferenceException' come si otterrebbe con un metodo di istanza regolare (anche uno che non fa riferimento a nessun membro). –

+0

Ha perfettamente senso perché funziona. I metodi di estensione non sono altro che metodi statici che vengono aggiunti a un oggetto. Davvero non c'è motivo per cui non dovrebbero funzionare. La classe non può dipendere da qualsiasi cosa facciano poiché non sono stati creati quando la classe originale era, e non possono accedere a nessuno dei metodi o oggetti privati. Sarebbe difficile impedire che venga utilizzato su un oggetto nullo (anche se ammetto che all'inizio sia un po 'strano). – kemiller2002

+1

Sì, il punto culminante di questa funzione è il metodo di estensione IfNotNull: 'public V IfNotNull (questo T @in, Func accesso)' – flq

4
string endString = string.IsNullOrEmpty(startString) ? startString : startString.Trim(); 

Anche se ho anche andato il percorso di scrittura di un metodo di estensione stringa chiamata "safeTrim", che fa quello che stai descrivendo in un metodo, invece di dover utilizzare questa ricetta ogni volta. Controlla Kevin's respone per il codice.

EDIT: wow ho avuto tutti i tipi di all'indietro, variabili chiamate a torto e invertito operatori ternari, una ragione in più per scrivere un metodo di estensione e il codice di controllo che meglio di me!

+1

Ninja-edited grazie al commento di Frank che mi ricorda che è 'string.IsNullOrEmpty (foo)' e non 'foo.IsNullOrEmpty()' –

+2

Controlli per vuoto. Non è quello che chiede –

+0

Ah, sì. All'inizio pensavo che "il controllo vuoto è un no-op efficace" perché il normale caso d'uso è quello di restituire semplicemente fine String' alla fine invece di 'null', ma alla fine avevo messo in modo esplicito' null'. Modificato nel caso d'uso normale e rende il controllo nulla efficacemente non operativo. –

1

Uso

string endString = (startString ?? "").Trim(); 

Questo utilizza una stringa vuoltare se inizioStringa è nullo. Questo, tuttavia, non produce non restituisce null quando endString è nullo.

+0

Se startString è nullo, vuole che endString sia nullo.Il tuo campione restituirà la stringa.Empty –

+0

È indicato nel post ... – AxelEckenberger

12

Non a spec: Non che mi piace, ma si può usare:

string endString = (startString ?? String.Empty).Trim(); 

a spec, meglio come un metodo di estensione, come @ Kevin:

string endString = (startString == null ? null : startString.Trim()); 
+2

Genius. Grazie! – rossipedia

+5

Non si propaga come richiesto per –

+3

questo non restituisce null se startString è null. –

0

Quanto segue non si propaga nullo ma accetta null come parametro e restituisce una stringa vuota in tal caso.

using Microsoft.VisualBasic; // you need to add a reference to Microsoft.VisualBasic.dll 

    ... 
    string endString = Strings.Trim(startString); 
    ... 

anatra & run ...

0

Creare un metodo come:

string MyTrim(string a) { 
    if (a != null) { 
     a = a.Trim(); 
    } 
    return a; 
} 
0

quanto come nota a margine, se si sta utilizzando .NET 4, c'è una nuova comoda metodo String.IsNullOrWhiteSpace che è possibile utilizzare.

+0

Metodo interessante, ma sembra ortogonale al problema che l'OP ha. – Brian

+0

Sì, mi dispiace, ho letto male la domanda ... –

1

Ci scusiamo per la negromanzia, ma stavo avendo lo stesso problema e l'ho risolto utilizzando un'operazione lambda. Non è il più bello, ma mantiene il mio codice succinto.

E 'un peccato C# non supporta le importazioni statiche o importazioni di funzioni individuali, ma in ogni caso:

Definire questa funzione da qualche parte:

private static TResult N<TParent,TResult>(TParent parent, Func<TParent,TResult> operation) { 
    if(parent == null) return default(TResult); 
    return operation(parent); 
} 

Poi usarlo nel tuo esempio:

String endString = N(startString, s => s.Trim()); 

La funzione N restituisce null se il primo argomento è nullo, altrimenti valuterà la funzione lambda specificata avanti con il valore come argomento.

È possibile nidificare, ovviamente, in questo modo. Ad esempio, per dereferenziare in sicurezza una lunga catena, ad es.

String someValue = someObject.SomeProperty.SomeOtherProperty.SomeMethod().SomeFinalProperty; 

se una di queste proprietà o metodi restituisce null allora è necessario inserire controlli nulli ovunque, o si potrebbe fare questo:

String someValue = N(N(N(N(someObject, o => o.SomeProperty), o => o.SomeOtherProperty), o => o.SomeMethod()), o => o.SomeFinalProperty); 

Come ho già detto, non è la più bella :)

Si potrebbe semplificare questo facendo N un metodo di estensione di System.Object, in questo modo:

String someValue = someObject.N(o => o.SomeProperty).N(o => o.SomeOtherProperty).N(o => o.SomeMethod()).N(o => o.SomeFinalProperty); 

... che penso sia molto più ordinato.

+0

Un generico con restrizioni di classe sembrerebbe migliore di 'System.Object', e penso che sarebbe bene avere alcune varianti che accettano vari numeri di parametri" extra ". Ci può essere un'enorme differenza di prestazioni tra un lambda che deve catturare qualsiasi cosa (incluso 'this') e uno che non lo fa, quindi consentire ai parametri di essere passati esplicitamente piuttosto che catturati può essere una grande vittoria. – supercat