IIF, a True Ternary Operator and Backwards Compatibility

One of the things we’ve been discussing for VB 9.0 is adding a true ternary operator to the language. It’s been a persistent source of annoyance for myself (and many others, to judge from suggestions and complaints we’ve gotten over the years) that there is no short-circuiting conditional expression operator in the language. True, there’s the IIF method which does most of what you want, but it doesn’t short-circuit. If you evaluate “IIF(x Is Nothing, 10, x.Foo())” and x is Nothing, then you’ll get an exception because we always evaluate all of the arguments of a method call (since IIF is just a regular method). In contrast, the C-style language’s ternary operator (i.e. “?:”, as in “x == null ? 10 : x.Foo()”) does short-circuit and it comes in mighty handy.

The annoyances get even worse with the introduction of queries into the language, because now there are a lot more places where you want to do in-line conditionals (since there aren’t statements in queries). In fact, I was a huge user of IIF back when I worked on the Access query designer in my previous life. So with LINQ coming, it’d be really nice to have a short-circuiting ternary operator available. So we’ve been pondering how best to do it. 

Rather than introduce some new operator, we’re considering doing to IIF what we did to AscW and ChrW and turning it into an intrinsic function. So even though IIF will still appear to be a function call, we’ll intercept the call and turn it into a true short-circuiting ternary operation. The nice thing is that you won’t have to learn any new syntax–things will just start working the way you expect them to. Probably 99% of programmers will never notice the change or like it. However, there probably will be that 1% of programmers (or maybe .1% of programmers or .01% of programmers) who will notice the change and be unpleasantly surprised. Perhaps you intentionally or unintentionally depended on the fact that all arguments to IIF would be evaluated, regardless of the value of the conditional expression. If so, when you recompile your application in VB 9, your program behavior will break or, even worse, silently change.

So what to do? Well, the language spec does say that we reserve the right to break compatibility for new features “only if the impact would be extremely minimal and the benefit of the feature is high.” I think, based on feedback we’ve collected, the second part of the test is no problem. The first part is the question. For example, we introduced some small compatibility breaks in the language when we added support for unsigned types (that might cause some method calls to bind to different overloads than before), but no one to date has ever reported an issue. So that’s a case where a new feature had a minimal compatibility impact and a high benefit. But what about this case?

Well, we’d like to know what people think. Our take on it is that it is extremely unlikely that anyone is consciously depending on the evaluation of both branches of the IIF expression. Extremely unlikely. And that anyone who’s unconsciously depending on the evaluation of both branches of the IIF expression is actually having a bug in their program covered up by a limitation of the language. If this is the case, then changing the behavior of IIF should help most people write more correct programs and should negatively impact very few people, if any at all.

Or will it? What’s your take?

I should also note that IIF currently doesn’t do the cute typing rules that you’d like from a ternary operator — that is, the return type of IIF is Object, so you have to cast in a lot of cases where you really shouldn’t have to. We’d also fix this at the same time (although we could also fix this by introducing a generic IIF method and fixing a few limitations of our generic inference algorithm–currently if a type parameter infers to two or more types, the algorithm fails rather than taking into account the situation where the type are all related to one another).

And one last huge CAVEAT EMPTOR: since we’re talking about pre-release software, do NOT construe this as a promise this feature will make it in to this release. Even though I believe it will get in, surprises always happen. So don’t start counting this particular chicken until you get actual bits that contain the feature. And even then, nothing’s final until we release to manufacturing.

(Bonus question: Why is it the “ternary operator?” It’s a bit of an imprecise name. An operator that takes one operand is a unary operator. An operator that takes two operands is a binary operator. And an operator that takes three operands…? Since “?:” is usually the only operator in C-style languages that takes three operands, the general “ternary operator” is applied to this specific operator. I imagine there are other names for it, this is just the one I’m used to hearing.)

60 thoughts on “IIF, a True Ternary Operator and Backwards Compatibility

  1. Vano

    1. New ternary operator behavior is what we all need.

    2. IMHO, keyword should differ (IFF is what I liked :), but syntax should be left the same, because it is actually optimal: "If condition Then t Else f" is too verbose and big and C-style is not readable. Thus, "If(condition, t, f)" is the best IMO.

  2. Patrik Hägne

    To me it seems that the best solution would actually be two solutions.

    Keep the IIF method but make it a generic method so that no casting is needed, this would ensure total backward compatibility.

    Implement ternary functionality for the if-operator like "x = If condition Then True Else False" this would ofcourse be using shortcut evaluation.

  3. Pingback: Panopticon Central

  4. Waiting for VB10

    What happened to this big bubble?? We’d all been full of hope, and then… duh!!! Nothing has changed, and VB9 came with the old useless IIF. For god sake, is there any reason for that? I’m a big VB fan, and hate the silly C alike syntax that’s short but not readable; nevertheless I’ve never used IIF because it is exactly useless for professional programming. But today I found myself forced to use it for the first time in my life, and it broke as expected because it is still in the old fashion (i.e. function) and has not been changed into an operator as I thought. Where I’ve had to use it, you may ask? Duh, here:

    In the latest ASP.NET, we’ve got declarative data binding using # (e.g. <%# Eval("fieldname") %>). As far as I know, we cannot use the normal if.then statement in this binding expression, thus we’ve got to use IIF, and no choice for someone like me to avoid it anymore. Well, as you said, this will break in many cases, let aside the performance cost of evaluating things that are not needed repeatedly when binding a data-grid for example. Someone might comment: but you can call a function in <%#…%> thus you can do whatever you like. Well my friend, of course this is what I’ve been doing so far, but can you think a bit further than your nose? Do you remember a fancy announcement about ASP.NET and the separation between the UI and code? As a general rule, the UI should depend as little as possible on the code-behind, and more importantly, we should try to avoid putting some UI in the code-behind. Example:

    To format the value of a data-field:

    <p>Price: <%#IIf(IsNumeric(Eval("Price")), FormatCurrency(Eval("Price").ToString), "N/A")%></p>

    Of course the IIF will break -as you know- so the solution is to create a function that formats the price, and call it instead of IIF. But what if my data-bound control (let’s say datalist) has many fields that need to be formatted in different ways? Then I will be creating so many functions and calling them from the UI only because the stupid IIF is misbehaving (actually behaving correctly, but in the old useless fashion). Isn’t this insane? While look at the example above how elegant it is if the IIF works in the logical and common-sense manner, as an operator? So now we’re waiting for VB10!!!

  5. Daniel Sampson

    In my opinion the IIF Ternary Operator should be short-circuited. It was no end of annoyance having a program fail because the False part could not be evaluated… Even though the Condition was True!

  6. Yisman

    Yup, were all waiting for a true shortcircuited IIF. its long overdue! this article is 2 years old and were still waitin in the cold…


  7. Pingback: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *