Domanda

Conosco il modo standard di utilizzare l'operatore Null coalescing in C # per impostare valori predefiniti.

string nobody = null;
string somebody = "Bob Saget";
string anybody = "";

anybody = nobody   ?? "Mr. T"; // returns Mr. T
anybody = somebody ?? "Mr. T"; // returns "Bob Saget"

Ma cos'altro si può usare ?? ? Non sembra utile come l'operatore ternario, a parte essere più conciso e più facile da leggere di:

nobody = null;
anybody = nobody == null ? "Bob Saget" : nobody; // returns Bob Saget

Quindi, dato che pochi sanno persino dell'operatore null coalescente ...

  • Hai usato ?? per qualcos'altro?

  • ?? è necessario o dovresti semplicemente usare l'operatore ternario (quello la maggior parte ha familiarità con)

È stato utile?

Soluzione

Bene, prima di tutto, è molto più facile concatenare rispetto al ternario standard:

string anybody = parm1 ?? localDefault ?? globalDefault;

vs.

string anyboby = (parm1 != null) ? parm1 
               : ((localDefault != null) ? localDefault 
               : globalDefault);

Funziona bene anche se l'oggetto null-possible non è una variabile:

string anybody = Parameters["Name"] 
              ?? Settings["Name"] 
              ?? GlobalSetting["Name"];

vs.

string anybody = (Parameters["Name"] != null ? Parameters["Name"] 
                 : (Settings["Name"] != null) ? Settings["Name"]
                 :  GlobalSetting["Name"];

Altri suggerimenti

L'ho usato come un liner a carico lento:

public MyClass LazyProp
{
    get { return lazyField ?? (lazyField = new MyClass()); }
}

leggibile? Decidi tu stesso.

L'ho trovato utile in due "leggermente dispari" modi:

  • In alternativa per avere un parametro out durante la scrittura delle routine TryParse (ovvero restituire il valore null se l'analisi non riesce)
  • Come " non so " rappresentazione per confronti

Quest'ultimo necessita di maggiori informazioni. In genere, quando si crea un confronto con più elementi, è necessario verificare se la prima parte del confronto (ad es. Età) fornisce una risposta definitiva, quindi la parte successiva (ad es. Nome) solo se la prima parte non è stata di aiuto. L'uso dell'operatore null coalescing significa che è possibile scrivere confronti piuttosto semplici (sia per l'ordinamento che per l'uguaglianza). Ad esempio, l'utilizzo di un paio di classi di supporto in MiscUtil :

public int Compare(Person p1, Person p2)
{
    return PartialComparer.Compare(p1.Age, p2.Age)
        ?? PartialComparer.Compare(p1.Name, p2.Name)
        ?? PartialComparer.Compare(p1.Salary, p2.Salary)
        ?? 0;
}

Devo ammettere che ora ho ProjectionComparer in MiscUtil, insieme ad alcune estensioni, che rendono questo tipo di cose ancora più semplice, ma è ancora pulito.

Lo stesso può essere fatto per verificare l'uguaglianza di riferimento (o nullità) all'inizio dell'implementazione di Equals.

Un altro vantaggio è che l'operatore ternario richiede una doppia valutazione o una variabile temporanea.

Consideralo, ad esempio:

string result = MyMethod() ?? "default value";

mentre con l'operatore ternario ti rimane uno dei due:

string result = (MyMethod () != null ? MyMethod () : "default value");

che chiama MyMethod due volte o:

string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");

Ad ogni modo, l'operatore a coalescenza nulla è più pulito e, immagino, più efficiente.

Un'altra cosa da considerare è che l'operatore di coalescenza non chiama il metodo get di una proprietà due volte, come fa il ternario.

Quindi ci sono scenari in cui non dovresti usare il ternario, ad esempio:

public class A
{
    var count = 0;
    private int? _prop = null;
    public int? Prop
    {
        get 
        {
            ++count;
            return _prop
        }
        set
        {
            _prop = value;
        }
    }
}

Se si utilizza:

var a = new A();
var b = a.Prop == null ? 0 : a.Prop;

il getter verrà chiamato due volte e la variabile count sarà uguale a 2 e se si utilizza:

var b = a.Prop ?? 0

la variabile count sarà uguale a 1, come dovrebbe.

Il più grande vantaggio che trovo per l'operatore ?? è che puoi facilmente convertire tipi di valore annullabili in tipi non annullabili:

int? test = null;
var result = test ?? 0; // result is int, not int?

Uso spesso questo nelle query Linq:

Dictionary<int, int?> PurchaseQuantities;
// PurchaseQuantities populated via ASP .NET MVC form.
var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);
// totalPurchased is int, not int?

L'ho usato ?? nella mia implementazione di IDataErrorInfo:

public string Error
{
    get
    {
        return this["Name"] ?? this["Address"] ?? this["Phone"];
    }
}

public string this[string columnName]
{
    get { ... }
}

Se una singola proprietà si trova in un "errore" stato ottengo quell'errore, altrimenti ottengo null. Funziona davvero bene.

Puoi usare l'operatore null coalescing per renderlo un po 'più pulito per gestire il caso in cui non è impostato un parametro opzionale:

public void Method(Arg arg = null)
{
    arg = arg ?? Arg.Default;
    ...

Mi piace usare l'operatore di coalescenza null per caricare in modo pigro determinate proprietà.

Un esempio molto semplice (e inventato) solo per illustrare il mio punto:

public class StackOverflow
{
    private IEnumerable<string> _definitions;
    public IEnumerable<string> Definitions
    {
        get
        {
            return _definitions ?? (
                _definitions = new List<string>
                {
                    "definition 1",
                    "definition 2",
                    "definition 3"
                }
            );
        }
    } 
}
  

È ?? necessario, o dovresti semplicemente usare l'operatore ternario (che la maggior parte conosce)

In realtà, la mia esperienza è che troppe poche persone hanno familiarità con l'operatore ternario (o più correttamente, l'operatore condizionale ; ?: è " ternary " in lo stesso senso che || è binario o + è unario o binario; tuttavia capita di essere l'unico operatore ternario in molte lingue), quindi almeno in quello campione limitato, la tua affermazione fallisce proprio qui.

Inoltre, come accennato in precedenza, c'è una situazione importante in cui l'operatore di coalescenza nulla è molto utile, e cioè quando l'espressione da valutare ha effetti collaterali. In tal caso, non puoi utilizzare l'operatore condizionale senza (a) introdurre una variabile temporanea o (b) modificare la logica effettiva dell'applicazione. (b) chiaramente non è appropriato in nessuna circostanza, e sebbene sia una preferenza personale, non mi piace ingombrare l'ambito della dichiarazione con molte variabili estranee, anche se di breve durata, quindi (a) è troppo fuori in questo scenario particolare.

Naturalmente, se è necessario eseguire più controlli sul risultato, l'operatore condizionale o un set di blocchi if , è probabilmente lo strumento per il lavoro. Ma per semplice "se questo è nullo, usalo, altrimenti usalo", l'operatore null coalescente ?? è perfetto.

L'unico problema è che l'operatore null-coalesce non rileva stringhe vuote.


cioè.

string result1 = string.empty ?? "dead code!";

string result2 = null ?? "coalesced!";

USCITA:

result1 = ""

result2 = coalesced!

Attualmente sto cercando di ignorare il ?? operatore per aggirare questo. Sarebbe sicuramente utile averlo integrato nel Framework.

Pensieri?

Una cosa che ho fatto molto ultimamente è usare la coalescenza nulla per i backup su come . Ad esempio:

object boxed = 4;
int i = (boxed as int?) ?? 99;

Console.WriteLine(i); // Prints 4

È anche utile per il backup di lunghe catene di ?. che potrebbero non riuscire

int result = MyObj?.Prop?.Foo?.Val ?? 4;
string other = (MyObj?.Prop?.Foo?.Name as string)?.ToLower() ?? "not there";
  

È ?? necessario o dovresti semplicemente usare l'operatore ternario (che la maggior parte ha familiarità)

Dovresti usare ciò che esprime meglio il tuo intento. Poiché è un operatore di coalescenza nullo, usalo .

D'altra parte, dal momento che è così specializzato, non penso che abbia altri usi. Avrei preferito un sovraccarico appropriato dell'operatore || , come fanno altre lingue. Questo sarebbe più parsimonioso nella progettazione del linguaggio. Ma bene ...

Cool! Contami come qualcuno che non sapeva dell'operatore di coalescenza nulla - è roba piuttosto ingegnosa.

Trovo molto più facile da leggere rispetto all'operatore ternario.

Il primo posto che mi viene in mente dove potrei usarlo è quello di mantenere tutti i miei parametri predefiniti in un unico posto.

public void someMethod( object parm2, ArrayList parm3 )
{ 
  someMethod( null, parm2, parm3 );
}
public void someMethod( string parm1, ArrayList parm3 )
{
  someMethod( parm1, null, parm3 );
}
public void someMethod( string parm1, object parm2, )
{
  someMethod( parm1, parm2, null );
}
public void someMethod( string parm1 )
{
  someMethod( parm1, null, null );
}
public void someMethod( object parm2 )
{
  someMethod( null, parm2, null );
}
public void someMethod( ArrayList parm3 )
{
  someMethod( null, null, parm3 );
}
public void someMethod( string parm1, object parm2, ArrayList parm3 )
{
  // Set your default parameters here rather than scattered through the above function overloads
  parm1 = parm1 ?? "Default User Name";
  parm2 = parm2 ?? GetCurrentUserObj();
  parm3 = parm3 ?? DefaultCustomerList;

  // Do the rest of the stuff here
}

Un po 'di uno strano caso d'uso, ma avevo un metodo in cui un oggetto IDisposable viene potenzialmente passato come arg (e quindi eliminato dal genitore), ma potrebbe anche essere nullo (e quindi dovrebbe essere creato e eliminato nel metodo locale)

Per usarlo, il codice era simile

Channel channel;
Authentication authentication;

if (entities == null)
{
    using (entities = Entities.GetEntities())
    {
        channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
        [...]
    }
}
else
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}

Ma con una coalescenza nulla diventa molto più ordinato

using (entities ?? Entities.GetEntities())
{
    channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
    [...]
}

Operatore a coalescenza nulla

Questo operatore controlla la variabile, se null, restituisce il valore accanto a & # 8220; ?? & # 8221; l'operatore else fornisce il valore salvato nella variabile.

Esempio: -1

var name=”ATHUL”;
var result =name ?? “The name is null”
Console.WriteLine(result);

o / p: ATHUL

Ad esempio: -2

var name=null;
var result =name ?? “The name is null”
Console.WriteLine(result);

o / p: il nome è null

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top