With the syntax as proposed, there's a concern that there will be an abundance of `ref` keywords in common code, leading to confusion. For instance, to store the selected variable above in a ref local would be:
Alternative proposal: Do not add new syntax for this. Instead, if both branches of an existing conditional expression are variables of the same type, let the compiler treat the conditional expression as a whole as a variable:
This would now mutate the *original*`v1` or `v2` of type `S`, instead of a copy! In practice such code today is probably buggy: why would you want to call a method to mutate a throw-away copy? But the fact remains that this would be a breaking change, unless we think up some very insidious mitigation.
An example of such a scheme would be to decide that a conditional is a variable, not based on what's *inside* it, but on what's *around* it. Whenever it's being used as a variable (
An approach is to define variable-ness of ternaries not from the inside out, but by "reinterpreting" it whenever it occurs in variable contexts not allowed today (ref, assignment).
This should also work for ["ref readonly"](https://github.com/dotnet/csharplang/issues/38), if and when that goes in. For that to work, we'd either need to require further syntax (`ref readonly` in the branches) or infer readonly-ness from the branches. The latter is more appetizing. We could:
Similarly we need to establish whether the resulting ref is safe-to-return. We can infer that the resulting ref is safe-to-return if both branches are safe-to-return.
There are subtle differences between the current spec and implementation when it comes to order of evaluation of an assignment. We need to make sure we fully understand how that plays in when the left hand side of an assignment is a conditional expression.
We want to allow program entry points (`Main` methods) that contain `await`. The temptation is to allow the `async` keyword on existing entry points returning `void` (or `int`?). However, that makes it *look* like an `async void` method, which is fire-and-forget, whereas we actually want program execution to wait for the main method to finish. So we'd have to make it so that if the method is invoked as an *entry* point we (somehow) wait for it to finish, whereas if it's invoked by another method, it is fire-and-forget.
C# 7.0 allows declaration of other "tasklike" types. We won't allow those in entry points yet, but that is easy to work around: Just `await` your tasklike in an `async Task Main`.