Sometimes, despite everyone’s best planning, you can’t help having features collide a bit. Thankfully, when it happens, there is almost always some way to reorganize the code to make it work. The key is to understand why your original code causes some issues.
I’ve written before about the new string interpolation feature in C# 6. I find it a welcome improvement over the previous incarnations.
Two goals of the feature are:
- It supports format specifiers for .NET types.
- It supports rich C# expression syntax between the braces.
Those two goals conflict because of the C# symbols used for each of them.
To specify a format for an expression, you place a colon ‘:’ after the expression, and then the remaining characters inside the braces consist of the format specifier. Here’s an example:
Console.WriteLine($"{DateTime.Now:MMM dd, yyyy}");
This will print the date in the form “Month day, year” where day is always a 2 digit number.
The C# compiler supports these format specifiers by interpreting the first ‘:’ character in a string
interpolation expression as the start of the format specifier. That works great, except in one case: where you want the colon to mean something else, like part of a conditional expression:
Console.WriteLine($"When {condition} is true, {condition ? "it's true!" : "It's False"}");
You can see that the syntax highlighting is getting a bit confused as it is not following the later string
correctly. That’s because the compiler interprets the ‘:’ as the beginning of a format specifier.
It’s easy to fix this. Just put the conditional expression inside parentheses:
Console.WriteLine($"When {condition} is true, {(condition ? "it's true!" : "It's False")}");
That way, the C# parser views everything inside the parentheses as part of the expression, and does not view the : as the beginning of a format specifier.
See? It’s easy to get both features to work. You just have to know why the first expression is interpreted differently than you’d expect.