有这两条线一样,“? ...:'VS'??'? [英] Are these two lines the same, '? ... :' 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屋!