有这两条线一样,“? ...:'VS'??'? [英] Are these two lines the same, '? ... :' vs '??'?

查看:188
本文介绍了有这两条线一样,“? ...:'VS'??'?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有这两条线之间的差异?



  MYNAME =(s.MyName == NULL)?的String.Empty:s.MyName 

  MYNAME = s.MyName?的String.Empty 


解决方案

更新:我写了一个博客贴子,讨论更深入这个话题。 http://www.codeducky.org/properties-fields-and-方法,哦,我的/






一般来说,他们将返回相同的结果。但是,也有少数情况下,您将体验到明显的差异,当 MYNAME 是一个属性,因为 MYNAME 方法会在第一个例子中的第二个例子执行两次和一次。



例如,可以从执行遇到性能差异 MYNAME 两次:

 字符串MYNAME 
{
得到
{
Thread.sleep代码(10000);
返回HELLO;
}
}



或者您也可以从执行<$ C得到不同的结果$ C> MYNAME 如果两次 MYNAME 是有状态:

 私人布尔_MyNameHasBeenRead = FALSE; 

串MYNAME
{
得到
{
如果(_MyNameHasBeenRead)
抛出新的异常(无法读取MYNAME两次) ;
_MyNameHasBeenRead = TRUE;
Thread.sleep代码(10000);
返回HELLO;
}
}



或者您也可以从执行<$ C得到不同的结果$ C> MYNAME 如果两次 MYNAME 可以在不同的线程进行更改:

 无效ChangeMyNameAsync()
{
// MYNAME设置为这使得它
//可能另一个线程空的第一个例子返回null
Task.Run(()=> this.MyName = NULL);
}

串MYNAME {搞定;组; }

下面是实际的代码是如何编译。首先,用一块三元表达式:

  IL_0007:// ldloc.0 US 
IL_0008:callvirt s.get_MyName < - 第一次调用
IL_000D:brfalse.s IL_0017
IL_000F:// ldloc.0 US
IL_0010:callvirt s.get_MyName< - 第二次调用
IL_0015: br.s IL_001C
IL_0017:ldsfld System.String.Empty
IL_001C:拨打set_MyName

和这里是一块与空合并运算符:

  IL_0007:// ldloc.0 US 
IL_0008:callvirt s.get_MyName< - 只能调用
IL_000D:DUP
IL_000E:brtrue.s IL_0016
IL_0010:弹出
IL_0011:ldsfld System.String.Empty
IL_0016:拨打s.set_MyName

正如你所看到的编译后的代码为三元运算符将两次调用来获得属性值,而空合并运算符只会做​​1。


Is there a difference between these two lines?

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

or

MyName = s.MyName ?? string.Empty

解决方案

UPDATE: I wrote a blog post that discusses this topic in more depth. http://www.codeducky.org/properties-fields-and-methods-oh-my/


Generally they will return the same result. However, there are a few cases where you will experience noticeable differences when MyName is a property because the MyName getter will be executed twice in the first example and only once in the second example.

For example, you may experience performance differences from executing MyName twice:

string MyName
{
    get 
    {
        Thread.Sleep(10000);
        return "HELLO";
    }
}

Or you may get different results from executing MyName twice if MyName is stateful:

private bool _MyNameHasBeenRead = false;

string MyName
{
    get 
    {
        if(_MyNameHasBeenRead)
                throw new Exception("Can't read MyName twice");
        _MyNameHasBeenRead = true;
        Thread.Sleep(10000);
        return "HELLO";
    }
}

Or you may get different results from executing MyName twice if MyName can be changed on a different thread:

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; }  

Here's how the actual code is compiled. First the piece with the ternary expression:

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

and here is the piece with the null-coalescing operator:

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

As you can see the compiled code for the ternary operator will make two calls to get the property value, whereas the null-coalescing operator will only do 1.

这篇关于有这两条线一样,“? ...:'VS'??'?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆