这两行有区别吗?
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/