这两行之间有区别吗?
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
这是null运算符的组成部分:
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
如您所见,三元运算符的编译代码将进行两次调用以获取属性值,而null-coalescing运算符将仅执行1。
关于c# - '? … :'和 '??'这两行是否相同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21052437/