myFoo = myFoo ?? new Foo();
вместо
if (myFoo == null) myFoo = new Foo();
Правильно ли я думаю, что первая строка кода всегда будет выполнять присваивание? Кроме того, это плохое использование оператора объединения с нулевым значением?
myFoo = myFoo ?? new Foo();
вместо
if (myFoo == null) myFoo = new Foo();
Правильно ли я думаю, что первая строка кода всегда будет выполнять присваивание? Кроме того, это плохое использование оператора объединения с нулевым значением?
Я сравнил CIL сгенерированного кода (обязательно выполнив сборку Release — с установленным флажком «Оптимизировать код» в свойствах проекта, что соответствует переключателю /optimize
на csc.exe
). Вот что я получил (используя VS 2008 - обратите внимание, что Foo.MaybeFoo()
- это метод, который иногда возвращает null
, иногда Foo
)
GetFooWithIf
:
IL_0000: call class Application3.Foo Application3.Foo::MaybeFoo()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brtrue.s IL_000f
IL_0009: newobj instance void Application3.Foo::.ctor()
IL_000e: stloc.0
IL_000f: ldloc.0
IL_0010: ret
GetFooWithCoalescingOperator
:
IL_0000: call class Application3.Foo Application3.Foo::MaybeFoo()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: dup
IL_0008: brtrue.s IL_0010
IL_000a: pop
IL_000b: newobj instance void Application3.Foo::.ctor()
IL_0010: stloc.0
IL_0011: ldloc.0
IL_0012: ret
Таким образом, то же самое, за исключением дополнительного дублирования вершины стека и всплывающего окна. Если это может привести к измеримой разнице в производительности, я куплю шляпу специально для того, чтобы ее съесть; поэтому используйте тот, который, по вашему мнению, обеспечивает лучшую читабельность.
(редактировать) о, и JITter может быть достаточно умен, чтобы избавиться даже от этой разницы!
csc.exe /optimize+
?
- person Pavel Minaev; 27.11.2009
class
, и все ссылки на объекты имеют одинаковый размер. Я уверен, что с struct
вы получите другой код. Но нам рекомендуется держать struct
s максимум в 16 байт, так что не намного хуже.
- person AakashM; 13.07.2012
Я не думаю, что это плохое использование оператора объединения с нулевым значением. При чтении кода он максимально краток и лаконичен, а цель кода очевидна.
Это правильно, что с помощью такого оператора объединения с нулевым значением вы всегда будете получать присваивание, но я бы не беспокоился об этом. (И если это действительно окажется проблемой с производительностью, вы уже знаете, как это исправить).
Вы правы в том, что первая строка всегда будет делать присваивание. Я бы не беспокоился об этом, если бы код не выполнялся очень часто.
myFoo
будет использоваться в другом месте кода и что это не позволит компилятору его оптимизировать. Если он не используется в другом месте, это другая история.
- person Fredrik Mörk; 24.11.2009
??=
:) - person Pavel Minaev   schedule 27.11.2009||=
? Ему пришлось бы заменить вызовif (!isset(myFoo)) myFoo = new Foo();
, чтобы гарантировать собственный оператор. - person Charlie Harding   schedule 23.12.2015||
требует логического значения. - person Pavel Minaev   schedule 23.12.2015