这两行之间有区别吗?
MyName = (s.MyName == null) ? string.Empty : s.MyName
要么
MyName = s.MyName ?? string.Empty
这两行之间有区别吗?
MyName = (s.MyName == null) ? string.Empty : s.MyName
要么
MyName = s.MyName ?? string.Empty
s.MyName一次还是两次。
diff它
Answers:
更新:我写了一篇博客文章,更深入地讨论了这个主题。 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。
MyName = s.MyName ?? string.Empty如果MyName是属性,则不会执行两次getter 。因此,如果您不想执行两次getter,则应使用第二行。
et_MyName应该是set_MyName。
?:由于null上述原因,带有的长版本可能实际上会导致这种情况。如果"Value from other thread"上面实际上是一个null字符串,则可能会更具有说明性。然后,这将表明结果可能为空。如果有状态对象决定在访问器的第一次调用中返回一个字符串实例,而get仅在第二次调用时返回null ,则有状态对象也会发生同样的情况。
如果该属性不仅仅是一个简单的getter,则在第一个非null情况下,您可能会执行两次函数。
如果该属性在有状态对象中,则对该属性的第二次调用可能返回不同的结果:
class MyClass
{
private IEnumerator<string> _next = Next();
public MyClass()
{
this._next.MoveNext();
}
public string MyName
{
get
{
var n = this._next.Current;
this._next.MoveNext();
return n;
}
}
public static IEnumerator<string> Next()
{
yield return "foo";
yield return "bar";
}
}
同样,在非字符串情况下,该类可能重载==来执行与三元运算符不同的操作。我不认为三元运算符可以重载。
?:。我还没有看过任何语言。
是的,两者相同,并且它是null-coalescing运算符。
如果操作数不为null,则返回左侧的操作数;否则返回0。否则返回右操作数。
如果我们谈论效率,那么
string MyName = (s.MyName == null) ? string.Empty : s.MyName;
string MyName2 = s.MyName ?? string.Empty;
如果我使用反汇编程序,则可以看到第一条语句需要19条语句才能由编译器执行,而第二条语句仅需要12条语句即可执行。
是的,他们也一样。??是检查null的简写。
不。两者都在做同一件事。第二个是有效的。如果不为空,则返回实际值。否则,将返回右侧值。
请参阅此http://msdn.microsoft.com/en-us/library/ms173224.aspx
希望这可以帮助。