c# - 这两行是否相同, '? ... :' 与 '??'?

标签 c#

这两行有区别吗?

MyName = (s.MyName == null) ? string.Empty : s.MyName

MyName = s.MyName ?? string.Empty

最佳答案

更新:我写了一篇博文更深入地讨论了这个话题。 http://www.codeducky.org/properties-fields-and-methods-oh-my/


通常他们会返回相同的结果。但是,在某些情况下,当 MyName 是一个属性时,您会体验到明显的差异,因为 MyName getter 在第一个示例中将执行两次,而在第二个示例中仅执行一次示例。

例如,执行两次 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 次。

关于c# - 这两行是否相同, '? ... :' 与 '??'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21052437/

相关文章:

c# - 组合框 SelectedItem 未按预期工作

c# - 如何在更改领域事件结构后检索历史事件

c# - 给定 Vector3 列表和距离,如何计算分段线上的点?

c# - 从 ASP.NET 应用程序获取入口程序集

c# - 通过 IKVM 在 C# 中用于 OIM 的 Java interface.class

c# - 如何使用流畅的界面构建序列?

c# - 在不可见的 Web 浏览器对象 C# 中模拟按键

c# - 使用 x :Bind with MvvmCross

c# - 检查是否已使用数组的所有值

c# - NUnit:如何只运行具有特定属性(优先级或类型)的测试