…I’d like to share it with you. Actually it’s some minor observations that suddenly came clashing together quite nicely.
Three state if-statements
The other day I read a discussion regarding the nullable object pattern. At first I thought it was mostly an academic idea – too much code for little or certainly questionable gain. Then all of a sudden I realized that I’ve been doing almost the same thing regularly for years. But I haven’t actually had a name for it. If I were to call it something I’d rather chose “default objects”. I too have made use of a construct that saves me repeated testing for null.
Yesterday I chatted with Mats Helander and we had the same feeling regarding expressions like this:
if ( x!=null && x.p==0 )
It is SO much simpler than having to write:
if ( x!=null )
if ( x.p==0 )
In this trivial case it is not really a big deal, but consider:
if ( x!=null && x.p!=0 && y!=null && y.p!=0 && z!=null && z.p!=0 )
// do something
else
// do something else
It gets really messy – especially the else part!
So what’s wrong with the first statement then? Well, it is mostly a feeling that it’s a hack. I really don’t like the idea that the order of evaluation of an expression should matter at all. If the compiler should like to evaluate my expression from right to left, it should by all means do so (although it, luckily, doesn’t). And again, this construct is really convenient.
I noticed that when working with strings, this type of expression:
if ( strName!=null && strName.Length!=0 )
kept reoccurring so often that I suggested to one of the members of the C# language team that a new keyword could be introduced, possibly called “empty”. It could look like this:
if ( !empty(strName) )
My idea was that the compiler would just produce the expanded version silently with no fuzz. One objection certainly is that a complier shouldn’t care about naming of properties – why would a compiler have something so say about a property being called “Length”? But as I see it, C# really does that already with the “using” statement! Apart from strings, this would work just as well with arrays. Maybe if a “Length” property wasn’t present, a “Count” property could be used…
He didn’t like the idea, saying that introducing new keywords may break existing code (when recompiling code where someone called a variable “empty”). That could easily be solved by not making the keyword reserved or by having compiler switches depending on what version of the language you wanted to compile, but of course, I agree that it probably wouldn’t be worth the trouble.
In C/C++ I wouldn’t hesitate a second before solving the problem like this:
#define empty(x) (x==null || x->Length==0)
But that little gem were left out of C#, probably for the better, considering all the creative stuff that has been accomplished using #define. (One of the weirdest uses I ever saw was from the Obfuscated C contest where someone had managed to write a program looking, except for the very first code line, like a circle!!! What it did? Computed pi, of course!)
So, were did all this take us? To the conclusion that checking for null is quite a big deal in modern OO languages, I’d say! The fact that the cumbersome nullable object pattern has been invented certainly speaks in favor this conclusion.
During my chat with Mats, when I was recapitulating all this, I happened to type an idea that I at first didn’t think much of, but now it has kept growing on me.
So, how would you, fellow programmers, feel about not having to worry about all this null reference checking when writing your if-statements? How about:
ifnotnull ( strName.Length!=0 )
This specialized if-statement would always be false if we were trying to access a property or method through a null reference! There would be not exceptions involved, just silently expanded code at compile time. For example:
ifnotnull ( a.b.c.d!=0 )
would expand to:
if ( a!=null && a.b!=null && a.b.c!=null && a.b.c.d!=0 )
Wouldn’t that be cool??? You almost start to wonder why it isn’t working that way by default!
(In practice, it wouldn’t be exactly the same thing; since the compiler would certainly be smart enough not to “start from the beginning” each time and ask “a” about “b” over and over for each part of the expression, giving rise to unnecessary method calls.)
Knowing myself, I think that I would start to write “ifnotnull” always, by routine. And seriously, isn’t that almost the same thing as the good old “On Error Resume Next” in plain old VB? Enough said.
Is the idea flawed for the beginning then? No, now comes the part that I (as of this writing) think is really brilliant. What if we gave the if-statement THREE states, instead of just “true” and “false”? The third state would be “null ref”. Well come on, you may say, “true”, “false” and “null” – what’s new in that? I see it everyday in my database, among others…
Well, consider this statement once more:
if ( a.b.c.d!=0 )
If we were to say that if is “true” or “false” if can be evaluated, but it is “null ref” if evaluating it would throw a null reference exception and we explicitly TEST for this condition. Or if we “catch” it, we could say – but then I don’t mean the “normal catch” that is used in conjunction with the try keyword.
I repeat this one more time, since it is important. The “null ref” state does not mean that the expression evaluates to “null”. It means that the expression can not be evaluated, because of a null reference!
So if we wrote:
if ( a.b.c.d!=0 )
// do something
else
// do something else
else null ref
// do yet something else
If the “else null ref” part is missing, then an exception would be thrown, just as usual. This way we explicitly state our intentions to the compiler and we aren’t severely violating any software engineering rules as I see it.
This could be precompiled into the following:
if ( a!=null && a.b!=null && a.b.c!=null )
{
if ( a.b.c.d!=0 )
// do something
else
// do something else
}
else
// do yet something else
Once again: this would have nothing to do with exceptions! No exception (due to null references) will be thrown, simply because they won’t happen! The compiler will test for them before they happen. Let’s say that a null reference exception was thrown from within the “a.b” property – then that won’t be “catched” by this new construct, simply because they are two totally different tings!
Being able to stuff together two of the three parts into one would be useful. This takes us dangerously close to “On Error Resume Next” again – not testing for abnormal conditions (if they really ARE abnormal, that can be argued), but I think we can get away with it. 😉
Some other possible language constructs:
if ( a.b.c.d==0 ) || null ref
// do what should be done when the expression is true
// or cannot be evaluated due to null references
else
// false part
As well as:
if ( a.b.c.d!=0 )
// do what should be done when the expression is true
else || null ref
// false part or null references
With this extension to the language I don’t have any use for my imaginary “empty” keyword anymore, since I could write:
if ( strName.Length!=0 )
// do what should be need to be done when the string isn't empty
else null ref; // tell the compiler that I'm really aware of what I'm doing!
Another possible syntax could be:
if ( strName.Length!=0 ) && !null ref
// do what should be need to be done when the string isn't empty
It would surprise me tremendously if this idea hasn’t been thought already. It may even have been implemented in other languages. But that doesn’t matter at all, as long as I can get it in C#!
(Note that I managed to do this without any new keyword! The language syntax graph grew more complex, however.)
To summarize: I think that “three state if-statements” would be a nice addition to just about any OO language. And as always: used correctly it could help writing more elegant and safer code. Used incorrectly, it would do just the opposite.