Ответ 1
UPDATE: я написал сообщение в блоге, которое более подробно обсуждает эту тему. 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.