Чи є різниця між цими двома рядками?
MyName = (s.MyName == null) ? string.Empty : s.MyName
або
MyName = s.MyName ?? string.Empty
Чи є різниця між цими двома рядками?
MyName = (s.MyName == null) ? string.Empty : s.MyName
або
MyName = s.MyName ?? string.Empty
s.MyNameодин або два рази.
diffце зробити
Відповіді:
ОНОВЛЕННЯ: Я написав допис у блозі, де детальніше розглядається ця тема. http://www.codeducky.org/properties-fields-and-methods-oh-my/
Як правило, вони повернуть той самий результат. Однак є кілька випадків, коли ви відчуєте помітні відмінності, колиMyName є властивістю, оскільки MyNameв першому прикладі геттер буде виконано двічі, а у другому - лише один раз.
Наприклад, у вас можуть виникнути відмінності в продуктивності від виконання MyName двічі:
string MyName
{
get
{
Thread.Sleep(10000);
return "HELLO";
}
}
Або ви можете отримати різні результати від виконання MyNameдвічі, якщо MyNameце має статус:
private bool _MyNameHasBeenRead = false;
string MyName
{
get
{
if(_MyNameHasBeenRead)
throw new Exception("Can't read MyName twice");
_MyNameHasBeenRead = true;
Thread.Sleep(10000);
return "HELLO";
}
}
Або ви можете отримати різні результати від виконання MyNameдвічі, якщо MyNameїх можна змінити в іншому потоці:
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; }
Ось як складається фактичний код. Спочатку фрагмент із потрійним виразом:
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
і ось шматок з оператором нульового злиття:
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
Як бачите, скомпільований код для тернарного оператора зробить два виклики, щоб отримати значення властивості, тоді як оператор нульового злиття зробить лише 1.
MyName = s.MyName ?? string.Emptyне буде виконувати геттер двічі, якщо MyNameє властивістю. Отже, якщо ви не хочете виконувати геттер двічі, то слід використати другий рядок.
et_MyName, що повинно бути set_MyName.
?:може насправді призвести nullз вищевказаних причин. Це може бути більш наочним, якби "Value from other thread"насправді це був nullрядок. Тоді це показало б, що результат може бути нульовим. Те саме може статися з об'єктом, що містить статус, якщо об'єкт вирішить повернути екземпляр рядка за першого виклику getaccessoor і повернути null лише для другого виклику.
Якщо властивість більше, ніж простий геттер, можливо, ви виконуєте функцію двічі у ненульовому випадку для першого.
Якщо властивість знаходиться у об’єкті, що містить статус, тоді другий виклик властивості може повернути інший результат:
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";
}
}
Крім того, у нестроковому випадку клас може перевантажити ==, щоб зробити щось інше, ніж тернарний оператор. Я не вірю, що потрійний оператор може бути перевантажений.
?:. Я не бачив жодної мови, яка б це робила.
Різниця лише в тому, оцінюєте ви s.MyNameдвічі чи один раз. Перший зробить це двічі у випадку, якщо s.MyNameне є нульовим значенням, другий лише колись оцінить це один раз.
У більшості випадків ця різниця не має значення, і я б погодився з другим, оскільки він є більш чітким і стислим.
Так, обидва є однаковими, і це оператор нульового злиття .
Він повертає лівий операнд, якщо операнд не є нульовим; в іншому випадку він повертає правий операнд.
Якщо говорити про ефективність, то
string MyName = (s.MyName == null) ? string.Empty : s.MyName;
string MyName2 = s.MyName ?? string.Empty;
Якщо я використовую дисемблер, то я бачу, що для першого оператора компілятор повинен виконати 19 операторів, тоді як для другого оператора потрібно було виконати лише 12 операторів .
Так, вони роблять те саме. ??це скорочення для перевірки на нуль.
Ні. Обидва роблять одне і те ж. Другий - ефективний. Що повертає фактичне значення, якщо воно не є нульовим. В іншому випадку буде повернуто значення правої сторони.
Зверніться до цього http://msdn.microsoft.com/en-us/library/ms173224.aspx
Сподіваюся, це допомагає.