Are these two lines the same? ...: 'vs' ?? '?

Is there a difference between the two lines?

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

or

 MyName = s.MyName ?? string.Empty 
+80
c #
Jan 10 '14 at 19:09
source share
7 answers

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




They usually return the same result. However, there are several cases where you notice noticeable differences when MyName is a property, as the MyName getter will be executed twice in the first example and only once in the second example.

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

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

Or you may get different results when running MyName twice if MyName has the status:

 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 can get different results from executing MyName twice if MyName can be changed in another 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 a piece with a triple 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 a piece with a zero 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 value of the property, while the operator with zero coalescing will only do 1.

+167
Jan 10 '14 at 19:12
source share

If the property is larger than a simple getter, you can execute the function twice in a non-zero case for the first.

If the property is in a stateful object, then the second call to the property may return a different result:

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

Also, in a case other than a string, the class may overload == to do something other than the ternary operator. I do not think that a ternary operator can be overloaded.

+26
Jan 10 '14 at 19:13
source share

The only difference is you evaluate s.MyName twice or once. The first will do this twice if s.MyName not null, the second will evaluate it only once.

In most cases, this difference does not matter, and I would go with the second, because it is more clear and concise.

+9
Jan 10 '14 at 21:40
source share

Yes, they are both the same, and this is a zero-connected operator .

It returns the left operand if the operand is not equal to zero; otherwise, it returns the right operand.

If we talk about efficiency, then

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

If I use a disassembler, then I see that the first statement requires 19 statements that must be executed by the compiler, while the second statement required only 12 statements to be executed.

+5
Jan 10 '14 at 19:12
source share

Yes, they do the same. ?? is a shorthand for checking a null value.

0
Jan 10 '14 at 19:11
source share

They perform the same task.

The only difference would be readability as to whether your colleagues understand or who reads the code, the syntax.

EDIT: Additionally, the first option can double-evaluate the MyName property.

0
Jan 10 '14 at 19:11
source share

No. Both are doing the same. The second is effective. Returns the actual value if it is not equal to zero. Otherwise, the value of the right side will be returned.

Refer to http://msdn.microsoft.com/en-us/library/ms173224.aspx

Hope this helps.

-one
Jan 10 '14 at 19:18
source share



All Articles