Open Rabadash8820 opened 4 years ago
@CyrusNajmabadi for the bad VS suggestion.
@alrz :)
@333fred I believe the bad VS suggestion has already been addressed by dotnet/roslyn#40236. @CyrusNajmabadi recommended I open a new issue here for the actual language feature request.
It seems inconsistent that you can do this with the ? operator but not with switch expressions
I am able to do the following with the ? operator
(lowerBound < upperBound ? ref lowerBound : ref upperBound) = mid;
But not with the switch expression
(lowerBound < upperBound ) switch
{
(true) => ref lowerBound,
(false) =>ref upperBound,
} = mid;
It just feels wrong that you are not able to do this in switch expressions
(lowerBound < upperBound ) switch { (true) => ref lowerBound, (false) =>ref upperBound, } = mid;
To be clear, there would be few more ref
mentions in the more maximal case of a ref-local assignment usage:
// v----- these -----v
ref double r_mid = ref (lowerBound < upperBound ) switch
{
true => ref lowerBound,
false => ref upperBound,
};
r_mid = mid;
// more later to amortize setting up 'r_mid', etc...
r_mid = updated_mid;
This is of course for consistency with standard/existing ref-local syntax applied to your ternary example:
ref double r_mid = ref (lowerBound < upperBound ? ref lowerBound : ref upperBound);
So now the only question is, when might it happen? I was actually quite surprised to discover this lurking omission, having been spoiled, in general, by the always impossibly-stellar C# design enterprise.
So now the only question is, when might it happen?
This issue is the any time bucket, meaning that it is open for community contributions (and likely won't happen until then). Currently, it needs an approved specification.
Adding to this, should the ability to specify ref
only once outside the body instead of in every case be considered? I can already foresee this being relatively repetitive in many cases. Something like,
return direction switch ref
{
Direction.North => NorthField,
Direction.South => SouthField,
Direction.East => EastField,
Direction.West => WestField,
_ => throw new NotImplementedException(),
};
Obviously the ref
would not actually apply to throw expressions, but their usage should still be permitted.
I've started creating a primitive spec for the current standing of the proposal to help this move forward.
A switch expression that returns a ref value does not need an extra ref in front of it when assigned/returned to a ref local.
FYI this is extremely unlikely to fly. The rules should be exactly the same as ref ternaries.
Now that I'm thinking about it, it makes sense to require that. I'll have it changed.
EDIT: Done
I'll champion this.
@Rekkonnect WRT to your spec, how close is it to the language/approach taken for ref-conditional expressions? Can you make a PR on this, and also link to the relevant existing ref-specs so we can compare?
This idea was already brought up in #2507, but the conclusion there was that:
However, switch expressions definitely still do not work the same way as ternary operators with respect to ref assignment, as others have noted in the Roslyn repo:
Long story short, suppose I have a
Direction
enum and want to conditionally do a ref assignment by switching on aDirection
instance, like so:Currently, Visual Studio suggests converting the switch statement to an expression, generating the following invalid code:
Each ref expression has a red squiggly saying
Invalid expression term 'ref'
, even if I addref
after thereturn
. If I keep theref
after thereturn
and delete all the case-specificref
s, then the whole switch block gets squiggled with the messageAn expression cannot be used in this context because it may not be passed or returned by reference
.I won't say "this should be easy to implement", cause I'm sure its not, but I see no reason why a ref assignment/return with a switch expression should be invalid syntax. Based on the conversation in #2507, I'm guessing the most likely implementation is to require ref after the return and in each case expression, but less typing is always better 🙂