Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Champion "conditional ref operator" (C# 7.2) #223

Open
4 of 5 tasks
gafter opened this issue Mar 3, 2017 · 17 comments
Open
4 of 5 tasks

Champion "conditional ref operator" (C# 7.2) #223

gafter opened this issue Mar 3, 2017 · 17 comments
Assignees
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion
Milestone

Comments

@gafter
Copy link
Member

gafter commented Mar 3, 2017

See also

The idea would be to support a version of the ?: operator that yields an lvalue. The current proposal is to do so using ref after the : and ?, for example

   (array1 != null ? ref array1[index] : ref dummy) = value;
   ref Node next = ref (node != null) ? ref node.Next : ref head;
@VSadov
Copy link
Member

VSadov commented Mar 3, 2017

@DavidArno - this was discussed:
Proposal: Add support for ternary ref expression

The proposal predates dotnet/csharplang, so it has not been moved to this repo yet.

@DavidArno
Copy link

@VSadov,

Ah cool, thanks.

@VSadov
Copy link
Member

VSadov commented Mar 3, 2017

There is also a PR with implementation. -
Implemented ref conditional operator (aka: ternary ref)

It is a relatively small feature. Basically a left over from the "ref returns".

@gafter
Copy link
Member Author

gafter commented Mar 3, 2017

@DavidArno This feature appeared in literally every example in the original feature request for ref locals and ref returns, but wasn't included in C# 7 along with the feature.

@lachbaer
Copy link
Contributor

lachbaer commented Mar 4, 2017

   (array1 == null ? ref array1[index] : ref dummy) = value;

Shouldn't it be array1 != null, or is my understanding of this feature wrong?
The reference to value cannot be stored in array1[index], if array1 doesn't exist...?!

@yaakov-h
Copy link
Member

yaakov-h commented Mar 4, 2017

How about null-conditional expressions, e.g. ref array1?[index] ?? ref dummy? Would that be possible?

@gafter
Copy link
Member Author

gafter commented Mar 4, 2017

@yaakov-h I don't understand your proposal, but in any case it is certainly a different feature request than this one. If you're requesting a different feature please open a new issue for that.

@gafter gafter added this to the 7.2 candidate milestone Mar 6, 2017
@alrz
Copy link
Member

alrz commented Apr 19, 2017

Can we do this instead?

ref (array1 != null ? array1[index] : dummy) = value;
ref Node next = ref (node != null ? node.Next : head);

@VSadov
Copy link
Member

VSadov commented Apr 20, 2017

@alrz - it would imply that (array1 != null ? array1[index] : dummy) is an LValue, which it is not.

That is easily observable if the expression returns a struct and you call a mutating method on it -
(array1 != null ? array1[index] : dummy).Mutate() - will not propagate mutations to the operands.

If the expression is supposed to be an LValue only as a part of ref assignment, then there is a need for more rules to figure when ternary is an LValue and when it is not, while being very careful with compat.
It gets more complicated when nested cases are considered.

And that is only to save typing one ref in a feature whose target audience often values explicitness.

@alrz
Copy link
Member

alrz commented Apr 20, 2017

I'm proposing that ref make it an lvalue if all branches are lvalue, same applies to other branching expressions as well,

ref (e1 ?? e2)
ref (e match { case P1: e1; case P2: e2; default: e3; })
ref (e1 ? e2 : e3)

Repeating ref on every branch AND the whole construct just seems redundant, IMHO.

@gafter gafter changed the title Champion "conditional ref operator" Champion "conditional ref operator" (C# 7.2) Sep 23, 2017
@paulomorgado
Copy link

@yaakov-h
Copy link
Member

It’s here now: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/conditional-ref.md

It should probably be moved and re-tagged since it’s missed the 7.2 release.

@VSadov
Copy link
Member

VSadov commented Feb 15, 2018

The feature is a part of 7.2
It was subsumed by the overall readonly ref theme which encompases multiple features related to the refs including conditional ref.

The up-to date description is a part of:
https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/readonly-ref.md

@yaakov-h
Copy link
Member

Ah.

Should this be closed as a duplicate, then? 😁

@ojb500
Copy link

ojb500 commented Jun 15, 2018

It seems that this does not play nicely with throw-expressions.
In particular, the requirement that 'ref' follows both the ? and the : means that expressions like this are not legal

public ref T this[int index] => index == 0 ? ref _thing : throw new IndexOutOfRangeException();

This isn't super critical but it does save typing compared to an explicit if (index == 0) throw ....

Apologies if this is not the right place to post this.

@svick
Copy link
Contributor

svick commented Jun 15, 2018

@ojb500 There's already a separate issue about that: #919.

@ojb500
Copy link

ojb500 commented Jun 15, 2018

@svick - somehow did not find that when searching, thanks for the response.

@333fred 333fred added the Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification label Oct 16, 2020
@VSadov VSadov removed their assignment Dec 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Implemented Needs ECMA Spec This feature has been implemented in C#, but still needs to be merged into the ECMA specification Proposal champion
Projects
None yet
Development

No branches or pull requests