C#学习教程:如果为null,则实例化变量分享♀?♀如果为null,则实例化变量if (x == null) x = new X(); 与 x = x ?? new X(); 这两个中哪一个实际上更高效? 一旦编译完成它们就会有效地结束( x = x;是NO-OP)? 查看中间语言代码有以下区别: .method private hidebysig instance void Method1() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldfld class X Program::x L_0006: brtrue.s L_0013 L_0008: ldarg.0 L_0009: newobj instance void X::.ctor() L_000e: stfld class X Program::x L_0013: ret } .method private hidebysig instance void Method2() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldarg.0 L_0002: ldfld class X Program::x L_0007: dup L_0008: brtrue.s L_0010 L_000a: pop L_000b: newobj instance void X::.ctor() L_0010: stfld class X Program::x L_0015: ret } 这是我为了得到这个而编译的代码: void Method1() { if (x == null) x = new X(); } void Method2() { x = x ?? new X(); } 要确定哪个更快,你应该两个时间。 方法初始条件每秒迭代次数 -------------------------------------------------- - NullCheck x为3300万 Coalesce x为3300万 NullCheck x不是4000万 Coalesce x不是3300万 结论: x不为null时的差异看起来可能是由于空合并运算符将x的值分配回x(IL中的stfld ),而当x不为null时,空检查会跳过stfld指令。 两者都是如此之快,你必须有一个非常紧密的循环来注意到差异。 如果您已使用数据分析代码,则应该只进行这些性能优化。 不同的情况,不同版本的.NET,不同的编译器等可能会产生不同的结果。 如果有人想知道我如何得到这些结果或重现它们,这里是我使用的代码: using System; class X { } class Program { private X x; private X xNull = null; private X xNotNull = new X(); private void Method1Null() { x = xNull; if (x == null) x = xNotNull; } private void Method2Null() { x = xNull; x = x ?? xNotNull; } private void Method1NotNull() { x = xNotNull; if (x == null) x = xNotNull; } private void Method2NotNull() { x = xNotNull; x = x ?? xNotNull; } private const int repetitions = 1000000000; private void Time(Action action) { DateTime start = DateTime.UtcNow; for (int i = 0; i { Method1Null(); }); Time(() => { Method2Null(); }); Time(() => { Method1NotNull(); }); Time(() => { Method2NotNull(); }); Console.WriteLine("Finished"); Console.ReadLine(); } private static void Main() { new Program().Run(); } } 免责声明:没有基准是完美的,这个bechmark 远非完美,主要是为了保持简单。 我已经运行了许多不同的测试,例如,使用不同顺序的方法,首先使用和不使用“预热”,在不同的时间长度等等。我每次都得到大致相同的结果。 我没有任何证据可以certificate这种或那种方式,所以任何有利于一种方法或另一种方法的偏见都是偶然的。 我不担心这种过早的优化。 我确信C#编译器的设计人员足够聪明,可以为你做这件事。 根本没有令人感兴趣的性能差异。 最重要的是if (x == null) x = new X(); 更具可读性 。 回答你原来的问题:一个聪明的优化编译器会编译x = x ?? new X() x = x ?? new X()的方式与if (x == null) x = new X(); 。 因此,在编译器上留下微优化,并专注于代码可读性和清晰度。 更新:要了解有关优化实践的更多信息,请阅读维基百科上的这篇文章 ,然后就Google问题的性质而言,谷歌“过早优化是所有邪恶的根源” 。 正如其他人所提到的,两者之间的性能差异并没有那么不同,但两者之间存在重要差异,尽管从你的例子中并不那么明显。 if (x == null) x = new X(); 创建一个潜在的竞争条件,其中x可以由检查null和创建之间的另一个线程新建,从而丢失一个对象。 x = x ?? new X(); 首先创建变量的副本,因此没有潜在的竞争条件。 在引用对象的情况下,这更是一个问题。 例如: 上述就是C#学习教程:如果为null,则实例化变量分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注— if (x != null) x.DoSomething(); // this can cause a null reference exception // if another thread nulls x between the check // and the call to DoSomething() (x = x ?? new X()).DoSomething() // this should be fine. 本文来自网络收集,不代表立场,如涉及侵权请点击右边联系管理员删除。如若转载,请注明出处:
