Archive
Gotcha: use parentheses around ternary op conditional expressions
Just came across the following case in C# that puzzled me momentarily, especially since the strings involved were long enough and the expression was broken on multiple lines:
bool flag = true;
string test1 = flag? "xa" : "xb";
string test2 = "x" + (flag? "a" : "b");
string test3 = "x" + flag? "a" : "b";
The test3 case fails since the compiler tries to evaluate the "x" + flag expression at the left side of the operator ?, complaining that it cannot implicitly convert string to bool.
e.g I accidentally produced the following wrong code while I was trying to refactor some third-party code to make it more readable:
string test3 = “some long string here” +
(someFlag)?
“some other long string”
:
“some alternative long string”;
whereas the correct was:
string test3 = “some long string here” +
( (someFlag)?
“some other long string”
:
“some alternative long string” );
The correct one needs the whole conditional expression enclosed in parentheses. In fact, the parentheses around (someFlag) can be skipped. In usually prefer them visually, even when I use just a boolean variable instead of a more complex boolean expression, but in case like this one the x + (someFlag)? a : b can be confusing to the reader of the code, not seeing x + (someFlag) will be treated as the conditional instead of someFlag.
Luckily the C# compiler is deterministic enough and not trying to imply meaning from one’s wrong syntax. Had it been some futuristic AI-based interpreter, well, it might have gotten confused there too.
To avoid this confusion in the first place, probably one could have designed a (bool)?x:y operator instead with parentheses being required around the boolean expression, but people coming from other languages (say C++) might then end up writing bool && (bool)?x:y and expect the condition to be bool && (bool) instead of just (bool), so even that syntax would be problematic.
Speaking of other languages, quoting from Wikipedia article on ternary operator:
C++
Unlike in C, the precedence of the
?:
operator in C++ is the same as that of the assignment operator (=
orOP=
), and it can return an lvalue. This means that expressions likeq ? a : b = c
and(q ? a : b) = c
are both legal and are parsed differently, the former being equivalent toq ? a : (b = c)
.
So confusion even between languages that share a C-style syntax might not be avoided.
Suggestion: Introduce .= operator for C#
It would be nice if one could write in C# (and maybe in other .NET languages too):
s = s.SomeMethodOfS(…)…
as
s .= SomeMethodOfS(…)…
that is to have a .= operator, similar to += and other shorthand experession operators
see screenshot for an example usecase from the opensource project FoscamController
Ideally, usage of such operators should lead to compiling – whether is is via JIT (Just in Time) or AOT (Ahead of Time) compilation – into more optimized native code, but I’m not sure if C# compilers are exploting that optimization opportunity.
You can vote up this suggestion at:
http://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/10724280-introduce-operator-for-c
Gotcha: no prefix increment/decrement VB.net operators, but get parsed
In C/C++ and C# one has useful prefix (++index) and postfix (index++) increment operators and corresponding decrement ones.
Although they have a single operant, they’re not working like functions as single + or – prefix would do, but instead they cause side-effects – they edit the variable passed to them. The prefix increment operator first increases a variable’s value, then returns it as result, while the postfix one first returns a variable’s value, then increases it.
Visual Basic.net doesn’t have such operators (and they don’t seem to plan to add such from their response on related feedback at Microsoft Connect.
However, if you type-in
Dim x = ++y
the compiler won’t complain. In fact, it won’t complain even if you type
Dim x = +++++y
The reason is because it thinks this last crazy-looking expression is:
Dim x = +(+(+(+(+y))))
Similarly, it accepts expressions like
Dim x = –y
and
Dim x = —–y
So a programmer coming from C# or converting C# code to VB.net has to be extra careful when converting ++index expressions to use their own implementation as a function that takes a ByRef parameter