Cosa significano insieme due punti interrogativi in ??C #?
-
22-07-2019 - |
Domanda
Ho attraversato questa riga di codice:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Cosa significano i due punti interrogativi, è una specie di operatore ternario? È difficile cercare su Google.
Soluzione
È l'operatore a coalescenza nulla, e abbastanza come l'operatore ternario (immediato). Vedi anche ?? Operatore - MSDN .
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
si espande in:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
che si espande ulteriormente in:
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
In inglese, significa " Se ciò che è a sinistra non è nullo, usalo, altrimenti usa ciò che è a destra. "
Nota che puoi usare un numero qualsiasi di questi in sequenza. La seguente dichiarazione assegnerà il primo risposta #
non null a Answer
(se tutte le risposte sono nulle, allora Answer
è null):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
Inoltre vale la pena ricordare che l'espansione sopra è concettualmente equivalente, il risultato di ogni espressione viene valutato solo una volta. Ciò è importante se ad esempio un'espressione è una chiamata di metodo con effetti collaterali. (Ringraziamo @Joey per averlo sottolineato.)
Altri suggerimenti
Solo perché nessun altro ha ancora detto le parole magiche: è l'operatore null coalescing . È definito nella sezione 7.12 del specifica del linguaggio C # 3.0 .
È molto utile, soprattutto per il modo in cui funziona quando viene usato più volte in un'espressione. Un'espressione del modulo:
a ?? b ?? c ?? d
darà il risultato dell'espressione a
se non è null, altrimenti prova b
, altrimenti prova c
, altrimenti prova d
. Cortocircuita in ogni punto.
Inoltre, se il tipo di d
è non annullabile, anche il tipo dell'intera espressione è non annullabile.
È l'operatore null coalescente.
http://msdn.microsoft.com/en-us/library/ ms173224.aspx
Sì, quasi impossibile cercare se non sai come si chiama! : -)
EDIT: e questa è una bella funzionalità di un'altra domanda. Puoi incatenarli.
Grazie a tutti, ecco la spiegazione più concisa che ho trovato sul sito MSDN:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
??
è lì per fornire un valore per un tipo nullable quando il valore è null. Quindi, se formsAuth è null, restituirà new FormsAuthenticationWrapper ().
I due punti interrogativi (??) indicano che si tratta di un operatore di coalescenza.
L'operatore di coalescenza restituisce il primo valore NON-NULL da una catena. Puoi vedere questo video di YouTube che dimostra praticamente tutto.
Ma vorrei aggiungere altro a ciò che dice il video.
Se vedi il significato inglese di coalescenza, dice & # 8220; consolidare insieme & # 8221 ;. Ad esempio, di seguito è riportato un semplice codice a coalescenza che incatena quattro stringhe.
Quindi se str1
è null
proverà str2
, se str2
è null
proverà str3
e così via finché non troverà una stringa con un valore non nullo.
string final = str1 ?? str2 ?? str3 ?? str4;
In parole semplici, l'operatore Coalescing restituisce il primo valore NON-NULL da una catena.
Se hai familiarità con Ruby, il suo || =
sembra simile al ??
di C # per me. Ecco un po 'di Ruby:
irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"
E in C #:
string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
È una scorciatoia per l'operatore ternario.
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
O per coloro che non fanno ternario:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
Niente di pericoloso al riguardo. In effetti è bellissimo. È possibile aggiungere un valore predefinito se ciò è desiderabile, ad esempio:
codice
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
Come indicato correttamente in numerose risposte che è l'operatore "null coalescing" ( ?? ), a proposito del quale potresti anche voler dare un'occhiata a suo cugino "Operatore Null-condizionale". (?. o ? [) che è un operatore che molte volte viene utilizzato insieme a ??
Utilizzato per verificare la presenza di null prima di eseguire un'operazione di accesso dei membri (?. ) o indice (? [). Questi operatori ti aiutano a scrivere meno codice per gestire i controlli null, specialmente per scendere nelle strutture di dati.
Ad esempio:
// if 'customers' or 'Order' property or 'Price' property is null,
// dollarAmount will be 0
// otherwise dollarAmount will be equal to 'customers.Order.Price'
int dollarAmount = customers?.Order?.Price ?? 0;
alla vecchia maniera senza ?. e ?? di farlo è
int dollarAmount = customers != null
&& customers.Order!=null
&& customers.Order.Price!=null
? customers.Order.Price : 0;
che è più prolisso e ingombrante.
Solo per tuo divertimento (sapendo che siete tutti ragazzi C # ;-).
Penso che abbia avuto origine in Smalltalk, dove esiste da molti anni. Qui è definito come:
in Object:
? anArgument
^ self
in UndefinedObject (aka classe zero):
? anArgument
^ anArgument
Esistono versioni di valutazione (?) e non di valutazione (??).
Si trova spesso nei metodi getter per variabili private (istanza) inizializzate in modo pigro, che vengono lasciate nulle fino a quando non sono veramente necessarie.
operatore di coalescenza
è equivalente a
FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
Alcuni esempi qui di ottenere valori usando la coalescenza sono inefficienti.
Quello che vuoi davvero è:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
o
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
Questo impedisce di ricreare l'oggetto ogni volta. Invece che la variabile privata rimanga nulla e un nuovo oggetto venga creato su ogni richiesta, questo assicura che la variabile privata venga assegnata se viene creato il nuovo oggetto.
Nota:
Ho letto tutta questa discussione e molte altre ma non riesco a trovare una risposta completa come questa.
Con la quale ho capito completamente il " perché usare ?? e quando usare ?? e come usare ??. "
Fonte:
Fondazione di comunicazione Windows scatenata da Craig McMurtry ISBN 0-672-32948-4
Tipi di valori nullable
Ci sono due circostanze comuni in cui si vorrebbe sapere se un valore è stato assegnato a un'istanza di un tipo di valore. Il primo è quando l'istanza rappresenta un valore in un database. In tal caso, si vorrebbe poter esaminare l'istanza per accertare se un valore è effettivamente presente nel database. L'altra circostanza, che è più pertinente all'argomento di questo libro, è quando l'istanza rappresenta un elemento di dati ricevuto da una fonte remota. Ancora una volta, si vorrebbe determinare dall'istanza se è stato ricevuto un valore per quell'elemento dati.
.NET Framework 2.0 incorpora una definizione di tipo generico che prevede casi come questi in cui si desidera assegnare null a un'istanza di un tipo di valore e verificare se il valore dell'istanza è null. Tale definizione di tipo generico è System.Nullable, che limita gli argomenti di tipo generico che possono essere sostituiti da T a tipi di valore. Alle istanze di tipi costruite da System.Nullable può essere assegnato un valore null; in effetti, i loro valori sono nulli per impostazione predefinita. Quindi, tipi costruiti da System.Nullable può essere indicato come tipi di valore nullable. System.Nullable ha una proprietà, Value, con cui il valore assegnato a un'istanza di un tipo costruito da esso può essere ottenuto se il valore dell'istanza non è nullo. Pertanto, si può scrivere:
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
Il linguaggio di programmazione C # fornisce una sintassi abbreviata per la dichiarazione dei tipi costruito da System.Nullable. Questa sintassi consente di abbreviare:
System.Nullable<int> myNullableInteger;
a
int? myNullableInteger;
Il compilatore impedirà a uno di tentare di assegnare il valore di un tipo di valore nullable a un tipo di valore ordinario in questo modo:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
Impedisce a uno di farlo perché il tipo di valore nullable potrebbe avere il valore null, che in realtà avrebbe in questo caso, e quel valore non può essere assegnato a un tipo di valore ordinario. Sebbene il compilatore consentirebbe questo codice,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
La seconda istruzione provocherebbe il lancio di un'eccezione a causa di qualsiasi tentativo accedere alla proprietà System.Nullable.Value è un'operazione non valida se il tipo costruito da System.Nullable non è stato assegnato un valore valido di T, cosa che non è avvenuta in questo caso.
Conclusione:
Un modo corretto per assegnare il valore di un tipo di valore nullable a un tipo di valore ordinario è utilizzare la proprietà System.Nullable.HasValue per accertare se un valore valido di T è stato assegnato al tipo di valore nullable:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
Un'altra opzione è utilizzare questa sintassi:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
Con cui viene assegnato al numero intero ordinario myInteger il valore dell'intero nullable "myNullableInteger" se a quest'ultimo è stato assegnato un valore intero valido; in caso contrario, a myInteger viene assegnato il valore -1.
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
è equivalente a
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
Ma la cosa bella è che puoi incatenarli, come hanno detto altre persone. L'unico aspetto non toccato è che puoi effettivamente usarlo per generare un'eccezione.
A = A ?? B ?? throw new Exception("A and B are both NULL");
L'operatore ??
è chiamato operatore a coalescenza nulla. Restituisce l'operando di sinistra se l'operando non è nullo; altrimenti restituisce l'operando di destra.
int? variable1 = null;
int variable2 = variable1 ?? 100;
Imposta variabile2
sul valore di variabile1
, se variabile1
NON è null;
altrimenti, se variabile1 == null
, imposta variabile2
su 100.
È un operatore a coalescenza nulla che funziona in modo simile a un operatore ternario.
a ?? b => a !=null ? a : b
Un altro punto interessante per questo è, " Un tipo nullable può contenere un valore oppure può essere indefinito " . Pertanto, se si tenta di assegnare un tipo di valore annullabile a un tipo di valore non annullabile verrà visualizzato un errore in fase di compilazione.
int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.
Quindi per farlo usando ?? operatore:
z = x ?? 1; // with ?? operator there are no issues