C# 6.0 multiple identical null conditional operator checks vs single traditional check
Asked Answered
M

2

11

Which out of the following two equivalent ways would be best for the null conditional operator in terms of primarily performance and then ease of use or clarity etc.?

This:

idString = child?.Id;
fatherName = child?.Father?.Name;
motherName = child?.Mother?.Name;

or (assuming that all local vars are null already) this:

if (child != null)
{
    idString = child.Id;
    fatherName = child.Father?.Name;
    motherName = child.Mother?.Name;    
}

Is performance even an issue?

Mister answered 6/12, 2016 at 9:56 Comment(4)
They're not equivalent - the latter code doesn't assign anything to the variables if child is null, whereas the former code will assign null values to all variables in that case. Decide what behaviour you want first, then choose what you find most readable, then validate that performance meets your requirements. (If you haven't yet defined your performance requirements, that's the first thing to do...)Vanover
These two are equivalent in the sense that they produce the same outcome. The outcome is guaranteed to be the same if, as I have pointed out, the local vars are already null.Mister
Ah, I didn't spot the "all local vars are null already". In that case, which do you prefer to read, and does that version meet your performance criteria? (You shouldn't just blindly go for "best" performance - most code isn't actually performance critical, but is readability critical.)Vanover
As for which gives better performance - measure it. You're saving two (child != null) checks, so there should be a difference, but it's probably not significant enough to override any readability issues.Sapper
R
13

Is performance even an issue?

Short answer: Performance about null-checks will never be an issue in a normal application. It's only a matter of readability and maintainability.

Performance:

Yes, you have 3 "explicit" checks against 1. But you must keep in mind that:

  1. The system performs an "implicit" null-check every time you reference an object instance, as explained here, and afaik the JIT doesn't optimize null-checks at all. So in your case the rate is not just 3 against 1.
  2. A null-check is a very (really, very) cheap operation, compared with most operations you do in a normal software flow (instance heap allocation, mathematic calculations, a linq query, graphic object rendering, string parsing, ...).

I see only a remote possibility of significant performance differences: if child or Mother or Father are not local variables or simple plain properties, but methods and properties with very long execution time. For example, a GetChild() method that takes 2 sec to execute. Can you see a realistic scenario for that? I can't. Even if that's the case, you can call GetChild() one single time and assign it to a local variable, then call child? 3 times.

Readability:

A single initial if allows to mentally separate different chunks of code. Pretend to be the reader of the code, without knowing anything else: ask yourself if is it simpler to read "if child is not null do all this operations and stuffs, otherwise just move on", or "if child is not null check the Name. If again child is not null check the Mother. If the Mother is not null get the Mother's Name. Then if again child is not null check the Father. If Father is not null... ... ... ".

Maintainability:

Aka, in this case, the DRY principle. For example, why would you repeat the null-check 3 times? Pretend that at a certain point in the future your boss asks to you a code change: it is required not only to check the nullity of a child, but also if its Id is 0 (things like that happen very frequently in any software development process). In your first code section you should correct 3 lines. In your second code section you should correct only 1 line: the initial if.

EDIT:

For a discussion about thread-safety on the null conditional operator, see this question.

Riesman answered 6/12, 2016 at 14:45 Comment(6)
Downvoter, you found 2 minutes to read my answer and - I guess - to understand it... could you please find 20-30 additional seconds to explain what am I missing?Riesman
I'm not the downvoter, but I can surmise that your post doesn't seem to be answering all parts of the the fundamental question as much as it seems be an excuse to bloviate on only one part. Keep your answers short and to the specific points raised in the question.Chilopod
@Chilopod it's always difficult for an Italian guy like me to express a thought with plain and short sentences, ahah... But SO is a good gym. I re-wrote my answer, but it's still long. Since the question touched performance, easy of use and clarity, it's the minimum to give some useful elements... isn't it? Do you see other removable/be simplified parts?Riesman
It reads well. Its informative. But its just too much information. Think about how the average user posts questions to SO. In this case it is just a quick thought someone had about coding style and performance implications. I would reel it in quite a bit. But, for what its worth, I never would have guessed you were not a native speaker. So, on that score, well done!Chilopod
+1 for the Maintainability comment with the DRY principle. Even though it is a long answer it is OK as the aim is not the solution to a specific problem but to address issues and confirm patterns that arise with the new null conditional operator.Mister
Actually, I feel like you have given the best answer and well explained to the original poster. Normally, the original poster need information like this, but other people who are in rush to get the quick answer are the one who feel distressed for reading too much information that they don't think they need but they have to read them. We've all been there.Millesimal
C
1

In second code example for variables will not set new values, but in first example they set as null or value from specified properties.

The ?. operator names like null-conditional operator. This operator works like:

With using ?.:

var result = someProperty?.someField;

Without using ?.:

if (someProperty != null)
    result = someProperty.someField;
else
    result = null;

About this operator you can read here: https://msdn.microsoft.com/en-us/library/dn986595.aspx.

It is better to use it in fluent of methods invoking. In your sample better to use second variant, because if child is null, then other actions are not perform.

Cowcatcher answered 6/12, 2016 at 12:36 Comment(3)
This doesn't answer his question.Cockleboat
Hm... I have explained what is the difference between the examples. Definitely say which is better, you can not depend on the context of use. The second is faster, but suddenly he must put Null values? What do not you like?Cowcatcher
The question was "Is performance even an issue?", which has more considerations such as readability & maintainability, the context in which this code runs (maybe this check's performance is meaningless because a huge algorithm runs right after anyway) etc... What you said isn't wrong it just doesn't say if "Performance is even an issue".Cockleboat

© 2022 - 2024 — McMap. All rights reserved.