Could we have a null coalescing, ternary operator (??::) in our c# armoury
I sometimes find myself writing something like the following when checking if a parent object is null before assignment:
string status;
if(parent == null)
{
status = "no parent";
}
else
{
status = parent.Status;
}
This to me seems long and cumbersome and only becomes more exaggerated if you need to check sub properties are not null.
string status;
if(parent == null)
{
status = "no parent";
}
else if (parent.Child == null)
{
status = "no child"
}
else if (parent.Child.Child == null)
{
status = "no grandchild"
}
else
{
status = parent.Child.Child.Status;
}
Now, I am aware of the new Safe Navigation ?. operator which does go some way to remedy this and I am looking forward to using it in anger, however, the only issue I see is that you lose the ability to identify at which point the object was null
which in some cases might be required.
var status = parent?.Child?.Child?.Name;
So I thought about it for a while. What are my options? How about a new operator?
###Null Coalescing Ternary operator (??::)
string status = parent ?? "no parent"
:: parent.Child ?? "no child"
:: parent.Child.Child ?? "no grandchild"
:: parent.Child.Child.Status;
Let me break the above down with comments
// parent is null assign "no parent"
string status = parent ?? "no parent"
// else if parent.Child is null assign "no child"
:: parent.Child ?? "no child"
// else if parent.Child.Child is null assign "no grandchild"
:: parent.Child.Child ?? "no grandchild"
// if all are not null, assign the grandchild status
:: parent.Child.Child.Status;
###The big readability question?
I understand that some people find the ternary operator less readable than if/else
statements, especially when nesting, and I tend to agree when it comes to having long nesting. So this idea might be dead in the water before it has even begun.
I personally put readability at the top of the priority list when performing code reviews or writing my own code, so the question is... Is the above more or less readable than the larger if/else example?
The above is merging two operators we are already aware of (null coalescing and ternary) so the learning curve should be small.
If you don't like the aforementioned operators, then chances are you're gonna loath this suggestion, and that's fine. I want to hear all arguments for and against this.
###What are your thoughts? I've been thinking about this on and off for a while. Will it be useful? Would you use such an operator? I'd like to hear your thoughts since I hear the ternary operator is not the most loved operator in the world, would this simply expand on an already 'out of love' operator.
If the feedback on this post is positive then I would consider submitting this to the Visual Studio UserVoice community. If the feedback is negative, I will not take offense, you will simply have saved me the embarrassment of putting a silly idea on to UserVoice.
If you would like to share your opinion, please use the comments form below. Alternatively, if you would prefer, feel free to get in touch with me via twitter @ninjanye
Hey John,
Neat! I certainly see the scenario. I believe the semantics of your proposal are equivalent to the current conditional (ternary) operator, except that the "condition" is checked against null instead of being evaluated as a boolean expression. So the consequent and alternative expressions don't have to be type-wise related to the "condition" - only to each other. Right?
If that's the case, then an alternative is to consider simply allowing non-boolean expressions as the condition in the current conditional operator. Those would be null-checked.
Then we wouldn't have to add new syntax; just say parent ? "no parent" : ...
.
Not saying this is necessarily better, but it would get us the same effect without new syntax.
Mads
Hi Mads,
Thanks for commenting. Your summary is correct, an alternative would be to expand the current ternary operator to allow for non-boolean expressions. You'd have largely the same code but it could potentially be more familiar
string status = parent ? "no parent"
: parent.Child ? "no child"
: parent.Child.Child ? "no grandchild"
: parent.Child.Child.Status;
Would this have a better chance of making through to becoming reality. I'm still not sure if I prefer hijacking the existing operator or creating a new one...
Cheers
John