Roslyn: Strange syntax error in interpolated string when using ?:

Created on 27 Jun 2016  路  20Comments  路  Source: dotnet/roslyn

$"{1 / Environment.TickCount == 0 ? 1 : 2}"

Here, the "1 " part has a red squiggly saying ": expected". I don't know whether this code is supposed to compile or not but the message does not make sense to me. I would not "expect" a ":" character right after the question mark under any circumstances.

The workaround $"{(1 / Environment.TickCount == 0 ? 1 : 2)}" works fine.

I guess this is a low priority issue but I still wanted to report it so that it can be triaged and tracked.

4 - In Review Area-Compilers Bug Concept-Diagnostic Clarity help wanted

Most helpful comment

The error will be

error CS8361: A conditional expression cannot be used directly in a string interpolation because the ':' ends the interpolation. Parenthesize the conditional expression.

All 20 comments

I don't think this is a bug, as it has been encountered before. As String Interpolation uses the syntax from String.Format, thus the : is being seen as part of the Argument Hole (spefically the formatting ).
By enclosing it in parenthesis, it gets treated as an expression.

Yes, that makes sense to me. But why does the error demand a ":" after the "?"?

I did't know. Guess would it be ambiguous

@GSPP that is because the : is treated as part of the string, not the expression, so the expression is missing a colon (which you cannot add without using parenthesis).

I see. So the error is trying to say that the colon is expected _after_ the "1" and not instead of it. I guess there is nothing to do here so I'm closing this.

@GSPP yep, not sure what build are you using but for

C# static void Main(string[] args) { var s = $"{1 / Environment.TickCount == 0 ? 1 |: 2}"; }

I get the ": expected" error before the colon as denoted by | which looks ok to me.

I think the error message is very confusing ("Colon expected? But I have a colon exactly where it should be."). Maybe it's worth keeping this open for the request to make the message better?

Well :-) turns out I have run into this myself: #4829 and suggested

If nothing else, it shouldn't say a colon is expected when there is a colon.

@gafter Might be worth having a less confusing error...

If it being the current state of the parser is that it is parsing the cond ? truth : falsehood why is the error being reported, Shouldn't it be seen it as part of that rather than the Argument Hole?

@AdamSpeight2008 Unfortunately, no. This is per the language specification. The parts of the interpolated string need to be identified during lexical analysis, which occurs long before parsing.

I insist that using "?:" operator inside an interpolated string handled WRONG WAY. We waited year while you discussing proper syntax for interpolation, and now, when you introduced these clumsy {} (instead of one symbol $ ), you say "it's not a bug". IT IS a bug. Once you limit substitution expression with braces {}, take full responsibility to handle it properly. And nobody care on what you base your formatting - we didn't ask you to use "string.Format" - we asked just simple substitution, like "Hello, $UserName!".

The error will be

error CS8361: A conditional expression cannot be used directly in a string interpolation because the ':' ends the interpolation. Parenthesize the conditional expression.

@gafter If the error message suggests a way to fix it, should the compiler also include a code fix that can do it automatically?

If the error message suggests a way to fix it, should the compiler also include a code fix that can do it automatically?

PRs welcome @svick :)

@svick @CyrusNajmabadi Created issue #23323 to track the suggested code fix.

Any expression, unary or sixnary, have to be completely parsed in interpolation string as a whole expression, NOT to intersecting with any "formatting" characters. It's just stupid - introduce feature to SIMPLIFY our life and make it so abstract/clumsy that it become UNUSABLE. What organ you use to think, team?? Just keep in your student head: $"... {a ? b : c}..." MUST WORK. Period. No excuses, no annoying explanations why you didn't make it properly.

@WrongBit can you please draft the language specification you prefer we use for the feature?

@gafter: I offered same solution like Nemerle has: dollar sign + verbatim mode. Better if these strings will have different quotes. Say, backtick (like in D). Finally it will look like this:

var s = ~bacltick here~ Today is $day
Temp is $temp
Last line of string~bacltick here~;

It's simple, CLEAR, obvious solution, usable for 99% cases. Where not, use old, good strings, Format(), etc.
Yes, it's not "hyper universal solution", but I'm tired of "universal architectors", who convert every task into idiotically complex solution (his code) and same idiotically complex usage (my code). Overengineering in other words.

@WrongBit that would be a completely new and different language construct, not a bug fix to the spec. New feature proposals belong in the csharplang repo, not here.

@WrongBit Note that nemerle has issues on its own (for example if you need an embedded string in your interpolation).

Any expression can be used in $(...), but there might be problems with embedded strings and so on.

That's similar to the case we have here in C#. In both languages you can type nearly anything in the interpolation. However, there are some cases that you need to provide additional syntax around.

It's simple, CLEAR, obvious solution, usable for 99% cases.

C#'s solution works for 99% of all cases as well :) Just for the case of ternary (where you just need to wrap things in parentheses to make it work). Seems similar to nemerle here :)

Was this page helpful?
0 / 5 - 0 ratings