wake-up-neo.net

Einzigartige Möglichkeiten, den Nullkoaleszenz-Operator zu verwenden

Ich weiß, die Standardmethode für die Verwendung des Null-Koaleszenzoperators in C # ist das Festlegen von Standardwerten.

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

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

Aber wozu kann ?? sonst noch verwendet werden? Es scheint nicht so nützlich wie der ternäre Operator zu sein, abgesehen davon, dass es übersichtlicher und leichter lesbar ist als:

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

In Anbetracht dessen, dass weniger sogar über nullkoaleszierende Operatoren wissen ...

  • Haben Sie ?? für etwas anderes verwendet?

  • Ist ?? erforderlich, oder sollten Sie nur den ternären Operator verwenden (mit dem die meisten ___ vertraut sind)

148
Armstrongest

Zunächst einmal ist es viel einfacher zu verketten als das Standard-Ternär:

string anybody = parm1 ?? localDefault ?? globalDefault;

vs.

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

Es funktioniert auch gut, wenn null mögliches Objekt keine Variable ist:

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

vs 

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

Ich habe es als Lazy Load One-Liner benutzt:

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

Lesbar? Entscheide dich selbst.

172

Ich habe es auf zwei "etwas seltsamen" Wegen für nützlich befunden:

  • Als Alternative zum Erstellen eines out-Parameters beim Schreiben von TryParse-Routinen (d. H. Den Nullwert zurückgeben, wenn die Analyse fehlschlägt).
  • Als "Weiß nicht" Darstellung für Vergleiche

Letzteres benötigt etwas mehr Informationen. Normalerweise müssen Sie beim Erstellen eines Vergleichs mit mehreren Elementen prüfen, ob der erste Teil des Vergleichs (z. B. Alter) eine endgültige Antwort ergibt, und den nächsten Teil (z. B. Name) nur dann, wenn der erste Teil nicht geholfen hat. Wenn Sie den Null-Koaleszenz-Operator verwenden, können Sie ziemlich einfache Vergleiche schreiben (ob für die Reihenfolge oder Gleichheit). Verwenden Sie beispielsweise einige Hilfsklassen 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;
}

Zugegeben, ich habe jetzt ProjectionComparer in MiscUtil zusammen mit einigen Erweiterungen, die diese Sache noch einfacher machen - aber es ist immer noch ordentlich.

Das Gleiche kann zur Überprüfung der Referenzgleichheit (oder Nullwertigkeit) zu Beginn der Implementierung von Equals durchgeführt werden.

51
Jon Skeet

Ein weiterer Vorteil besteht darin, dass der ternäre Operator eine doppelte Auswertung oder eine temporäre Variable benötigt.

Betrachten Sie dies zum Beispiel:

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

während Sie mit dem ternären Operator stehen, bleibt Ihnen entweder:

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

die MyMethod zweimal aufruft, oder:

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

In jedem Fall ist der Nullkoaleszenzoperator sauberer und, ich denke, effizienter.

32
Mario Cossi

Zu beachten ist auch, dass der coalesce-Operator die get-Methode einer Eigenschaft nicht zweimal aufruft, wie dies der ternäre Operator tut.

Es gibt also Szenarien, in denen Sie nicht ternär verwenden sollten, zum Beispiel:

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

Wenn du benutzt: 

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

der Getter wird zweimal aufgerufen und die Variable count ist gleich 2, und wenn Sie Folgendes verwenden:

var b = a.Prop ?? 0

die Variable count ist wie gewünscht gleich 1.

20
Fabio Lima

Der größte Vorteil, den ich für den ??-Operator finde, besteht darin, dass Sie nullfähige Wertetypen einfach in nicht-nullfähige Typen konvertieren können:

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

Ich verwende das häufig in Linq-Abfragen:

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

Habe ich benutzt ?? in meiner Implementierung von IDataErrorInfo:

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

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

Wenn sich eine einzelne Eigenschaft in einem Fehlerzustand befindet, erhalte ich diesen Fehler. Funktioniert sehr gut.

9
Matt Hamilton

Sie können den Nullkoaleszenzoperator verwenden, um den Fall, in dem kein optionaler Parameter festgelegt ist, ein wenig sauberer zu machen:

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

Ist ?? notwendig, oder sollten Sie nur den ternären Operator verwenden (mit dem die meisten vertraut sind)

Meine Erfahrung ist eigentlich, dass nur zu wenige Personen mit dem ternären Operator vertraut sind (oder, genauer gesagt, der bedingte-Operator; ?: ist "ternär" in dem Sinne, dass || binär ist oder + entweder unär oder unär ist binär (es ist jedoch in vielen Sprachen der einzige ternäre Operator), so dass Ihre Aussage zumindest in diesem begrenzten Beispiel nicht richtig funktioniert.

Wie bereits erwähnt, gibt es eine Hauptsituation, in der der Nullkoaleszenzoperator sehr nützlich ist, und zwar immer dann, wenn der auszuwertende Ausdruck überhaupt Nebenwirkungen hat. In diesem Fall verwenden Sie kann nicht den Bedingungsoperator, ohne (a) eine temporäre Variable einzuführen oder (b) die tatsächliche Logik der Anwendung zu ändern. (b) ist eindeutig unter keinen Umständen angemessen, und obwohl es eine persönliche Präferenz ist, mag ich es nicht, den Deklarationsumfang mit einer Menge überflüssiger, selbst wenn auch kurzlebiger Variablen zu überspielen. Daher ist (a) auch in dieser Hinsicht nicht zu finden bestimmten Szenario.

Wenn Sie das Ergebnis mehrfach überprüfen müssen, sind der Bedingungsoperator oder eine Gruppe von if-Blöcken wahrscheinlich das Werkzeug für den Job. Aber für einfache "Wenn dies null ist, verwenden Sie das, sonst verwenden Sie es", ist der Nullkoaleszenzoperator ?? perfekt.

5
a CVn

Ich benutze gerne den Null-Koaleszenz-Operator, um bestimmte Eigenschaften zu faulenzen.

Ein sehr einfaches (und einfallsreiches) Beispiel, um meinen Standpunkt zu veranschaulichen:

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

Das einzige Problem ist, dass der Null-Koaleszenz-Operator keine leeren Zeichenfolgen erkennt. 


d.h.

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

string result2 = null ?? "coalesced!";

AUSGABE:

result1 = ""

result2 = coalesced!

Ich bin gerade dabei, das zu überschreiben ?? Operator, um dies zu umgehen. Es wäre sicher praktisch, dies in das Framework einzubauen.

Gedanken?

4
whatispunk

Eine Sache, die ich in letzter Zeit häufig gemacht habe, ist die Verwendung von Null-Koaleszenz für Backups in as. Zum Beispiel:

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

Console.WriteLine(i); // Prints 4

Es ist auch nützlich, um lange Ketten von ?. zu sichern, die jeweils ausfallen könnten

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

Ist ?? notwendig, oder sollten Sie nur den ternären Operator verwenden (mit dem die meisten vertraut sind)

Sie sollten das verwenden, was Ihre Absicht am besten zum Ausdruck bringt. Da ist ein Null-Koaleszierungsoperator, benutzt es .

Auf der anderen Seite, da es so spezialisiert ist, glaube ich nicht, dass es andere Zwecke hat. Ich hätte eine angemessene Überladung des ||-Operators vorgezogen, wie dies bei anderen Sprachen der Fall ist. Dies wäre im Sprachdesign sparsamer. Aber gut …

3
Konrad Rudolph

Cool! Zählen Sie mich zu jemandem, der nichts über den Null-Koaleszenz-Operator wusste - das ist ziemlich schickes Zeug.

Ich finde es viel einfacher zu lesen als der ternäre Operator.

Der erste Ort, an den ich mich erinnere, ist, alle meine Standardparameter an einem Ort zu behalten.

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
}
3
HanClinto

Etwas ungewöhnlicher Anwendungsfall, aber ich hatte eine Methode, bei der ein IDisposable-Objekt möglicherweise als arg übergeben wird (und daher von einem übergeordneten Element entsorgt wird), es könnte jedoch auch null sein (und sollte daher in der lokalen Methode erstellt und verworfen werden).

Um es zu verwenden, sah der Code entweder so aus

Channel channel;
Authentication authentication;

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

Aber mit einer Nullverschmelzung wird viel netter

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

Nullkoaleszenzoperator

Dieser Operator überprüft die Variable. Wenn der Wert null ist, wird der Wert neben dem Operator "??" zurückgegeben. Andernfalls wird der in der Variablen gespeicherte Wert angegeben.

ZB: -1

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

o/p: ATHUL

ZB: -2 

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

o/p: Der Name ist null

0