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
gafter opened this Issue Mar 3, 2017 · 17 comments

Comments

Projects
None yet
10 participants
@gafter
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

This comment has been minimized.

Show comment
Hide comment
@VSadov

VSadov Mar 3, 2017

Member

@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.

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

This comment has been minimized.

Show comment
Hide comment
@DavidArno

DavidArno Mar 3, 2017

@VSadov,

Ah cool, thanks.

DavidArno commented Mar 3, 2017

@VSadov,

Ah cool, thanks.

@VSadov

This comment has been minimized.

Show comment
Hide comment
@VSadov

VSadov Mar 3, 2017

Member

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".

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

This comment has been minimized.

Show comment
Hide comment
@gafter
Member

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

This comment has been minimized.

Show comment
Hide comment
@lachbaer

lachbaer Mar 4, 2017

Contributor
   (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...?!

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

This comment has been minimized.

Show comment
Hide comment
@yaakov-h

yaakov-h Mar 4, 2017

Contributor

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

Contributor

yaakov-h commented Mar 4, 2017

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

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Mar 4, 2017

Member

@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.

Member

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

This comment has been minimized.

Show comment
Hide comment
@alrz

alrz Apr 19, 2017

Contributor

Can we do this instead?

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

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

This comment has been minimized.

Show comment
Hide comment
@VSadov

VSadov Apr 20, 2017

Member

@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.

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

This comment has been minimized.

Show comment
Hide comment
@alrz

alrz Apr 20, 2017

Contributor

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.

Contributor

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 from Champion "conditional ref operator" to Champion "conditional ref operator" (C# 7.2) Sep 23, 2017

@yaakov-h

This comment has been minimized.

Show comment
Hide comment
@yaakov-h

yaakov-h Feb 15, 2018

Contributor

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.

Contributor

yaakov-h commented Feb 15, 2018

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

This comment has been minimized.

Show comment
Hide comment
@VSadov

VSadov Feb 15, 2018

Member

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

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

This comment has been minimized.

Show comment
Hide comment
@yaakov-h

yaakov-h Feb 16, 2018

Contributor

Ah.

Should this be closed as a duplicate, then? 😁

Contributor

yaakov-h commented Feb 16, 2018

Ah.

Should this be closed as a duplicate, then? 😁

@ojb500

This comment has been minimized.

Show comment
Hide comment
@ojb500

ojb500 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.

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

This comment has been minimized.

Show comment
Hide comment
@svick

svick Jun 15, 2018

Contributor

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

Contributor

svick commented Jun 15, 2018

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

@ojb500

This comment has been minimized.

Show comment
Hide comment
@ojb500

ojb500 Jun 15, 2018

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

ojb500 commented Jun 15, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment