Gibt es einen Unterschied zwischen diesen beiden Zeilen?
MyName = (s.MyName == null) ? string.Empty : s.MyName
oder
MyName = s.MyName ?? string.Empty
Gibt es einen Unterschied zwischen diesen beiden Zeilen?
MyName = (s.MyName == null) ? string.Empty : s.MyName
oder
MyName = s.MyName ?? string.Empty
s.MyNameein- oder zweimal bewerten .
diffes
Antworten:
UPDATE: Ich habe einen Blog-Beitrag geschrieben, in dem dieses Thema ausführlicher behandelt wird. http://www.codeducky.org/properties-fields-and-methods-oh-my/
Im Allgemeinen geben sie das gleiche Ergebnis zurück. Es gibt jedoch einige Fälle, in denen Sie merkliche Unterschiede feststellen, wenn MyNamees sich um eine Eigenschaft handelt, da der MyNameGetter im ersten Beispiel zweimal und im zweiten Beispiel nur einmal ausgeführt wird.
Beispielsweise können bei MyNamezweimaliger Ausführung Leistungsunterschiede auftreten :
string MyName
{
get
{
Thread.Sleep(10000);
return "HELLO";
}
}
Oder Sie erhalten unterschiedliche Ergebnisse, MyNamewenn Sie zweimal ausführen, wenn dies MyNamezustandsbehaftet ist:
private bool _MyNameHasBeenRead = false;
string MyName
{
get
{
if(_MyNameHasBeenRead)
throw new Exception("Can't read MyName twice");
_MyNameHasBeenRead = true;
Thread.Sleep(10000);
return "HELLO";
}
}
Oder Sie erhalten unterschiedliche Ergebnisse, MyNamewenn Sie zweimal ausgeführt werden, wenn MyNamedies in einem anderen Thread geändert werden kann:
void ChangeMyNameAsync()
{
//MyName set to null in another thread which makes it
//possible for the first example to return null
Task.Run(() => this.MyName = null);
}
string MyName { get; set; }
So wird der eigentliche Code kompiliert. Zuerst das Stück mit dem ternären Ausdruck:
IL_0007: ldloc.0 // s
IL_0008: callvirt s.get_MyName <-- first call
IL_000D: brfalse.s IL_0017
IL_000F: ldloc.0 // s
IL_0010: callvirt s.get_MyName <-- second call
IL_0015: br.s IL_001C
IL_0017: ldsfld System.String.Empty
IL_001C: call set_MyName
und hier ist das Stück mit dem Null-Koaleszenz-Operator:
IL_0007: ldloc.0 // s
IL_0008: callvirt s.get_MyName <-- only call
IL_000D: dup
IL_000E: brtrue.s IL_0016
IL_0010: pop
IL_0011: ldsfld System.String.Empty
IL_0016: call s.set_MyName
Wie Sie sehen können, führt der kompilierte Code für den ternären Operator zwei Aufrufe durch, um den Eigenschaftswert abzurufen, während der Null-Koaleszenz-Operator nur 1 ausführt.
MyName = s.MyName ?? string.Emptyführt den Getter nicht zweimal aus, wenn MyNamees sich um eine Eigenschaft handelt. Wenn Sie den Getter also nicht zweimal ausführen möchten, sollten Sie die zweite Zeile verwenden.
et_MyName, was sein sollte set_MyName.
?:könnte nullaus den oben genannten Gründen tatsächlich dazu führen . Es könnte anschaulicher sein, wenn "Value from other thread"oben tatsächlich eine nullZeichenfolge wäre. Dann zeigt , dass würde , dass das Ergebnis könnte null sein. Dasselbe kann mit dem statusbehafteten Objekt passieren, wenn das Objekt beim ersten Aufruf des getZugriffs eine Zeichenfolgeninstanz zurückgibt und beim zweiten Aufruf nur null zurückgibt.
Wenn die Eigenschaft mehr als ein einfacher Getter ist, führen Sie möglicherweise eine Funktion zweimal im Nicht-Null-Fall für die erste aus.
Befindet sich die Eigenschaft in einem statusbehafteten Objekt, gibt der zweite Aufruf der Eigenschaft möglicherweise ein anderes Ergebnis zurück:
class MyClass
{
private IEnumerator<string> _next = Next();
public MyClass()
{
this._next.MoveNext();
}
public string MyName
{
get
{
var n = this._next.Current;
this._next.MoveNext();
return n;
}
}
public static IEnumerator<string> Next()
{
yield return "foo";
yield return "bar";
}
}
Im Fall ohne Zeichenfolge kann die Klasse außerdem == überladen, um etwas anderes als den ternären Operator zu tun. Ich glaube nicht, dass der ternäre Operator überlastet werden kann.
?:. Ich habe keine Sprache gesehen, die das tut.
Der einzige Unterschied besteht darin, ob Sie s.MyNamezweimal oder einmal bewerten . Der erste wird es zweimal tun, wenn s.MyNamees nicht null ist, der zweite wird es immer nur einmal auswerten.
In den meisten Fällen spielt dieser Unterschied keine Rolle, und ich würde mich für den zweiten entscheiden, weil er klarer und prägnanter ist.
Ja, beide sind gleich und es ist der Null-Koaleszenz-Operator .
Es gibt den linken Operanden zurück, wenn der Operand nicht null ist. Andernfalls wird der rechte Operand zurückgegeben.
Wenn wir dann über Effizienz sprechen
string MyName = (s.MyName == null) ? string.Empty : s.MyName;
string MyName2 = s.MyName ?? string.Empty;
Wenn ich einen Dissembler verwende, kann ich sehen, dass für die erste Anweisung 19 Anweisungen vom Compiler ausgeführt werden müssen, während für die zweite Anweisung nur 12 Anweisungen ausgeführt werden müssen.
Ja, sie machen das Gleiche. ??ist eine Abkürzung für die Überprüfung auf Null.
Nein, beide machen das Gleiche. Der zweite ist effizient. Dies gibt den tatsächlichen Wert zurück, wenn er nicht null ist. Andernfalls wird der Wert auf der rechten Seite zurückgegeben.
Weitere Informationen finden Sie unter http://msdn.microsoft.com/en-us/library/ms173224.aspx
Hoffe das hilft.