I posted a similar question to the Roslyn issues and was given the answer by DavidArno:
It's long, but you can read all the gory details of why the language
design team chose to "enhance" the language in this way at #12939.
TL;DR you aren't alone in thinking the change unintuitive and
contradictory to the way scope have worked before. The team sadly
don't care though and the change is here to stay.
It seems the decision was made that this scoping would apply, so the spec is now out of date, and this scoping is sadly here to stay:
Option 3: Expression variables are scoped by blocks, for, foreach and
using statements, as well as all embedded statements:
What is meant by an embedded statement here, is one that is used as a
nested statement in another statement - except inside a block. Thus
the branches of an if statement, the bodies of while, foreach, etc.
would all be considered embedded.
The consequence is that variables would always escape the condition of
an if, but never its branches. It's as if you put curlies in all the
places you were "supposed to".
Conclusion
While a little subtle, we will adopt option 3. It strikes a good
balance:
It enables key scenarios, including out vars for non-Try methods, as
well as patterns and out vars in bouncer if-statements. It doesn't
lead to egregious and counter-intuitive multi-level "spilling". It
does mean that you will get more variables in scope than the current
restrictive regime. This does not seem dangerous, because definite
assignment analysis will prevent uninitialized use. However, it
prevents the variable names from being reused, and leads to more names
showing in completion lists. This seems like a reasonable tradeoff.
iat a higher scope, but it's hard to tell since it's a code snippet for beta functionality. I guess you could get the preview and test it out. - juharr