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

Proposal: null-coalescing assignment operator ??= #13737

Closed
alireza-naghizadeh opened this issue Sep 12, 2016 · 15 comments
Closed

Proposal: null-coalescing assignment operator ??= #13737

alireza-naghizadeh opened this issue Sep 12, 2016 · 15 comments

Comments

@alireza-naghizadeh
Copy link

Proposal
I'd like to propose an idea for next C#, with name: null-coalescing assignment operator
We can combine the ?? and = operators (??=) like, += and -= ...

Sample:
myObject.MyStringList ??= new List<string>();
Assign if the left is null...
In C# 6 we had:
myObject.MyStringList = myObject.MyStringList ?? new List<string>();

Another sample:
(myObject.MyStringList ??= new List<string>()).Add("something");

This is very simple, but useful...
Thanks

@HaloFour
Copy link

Dupe of #205, #3366, #5163, #10249, #10556, #11394 and #12606.

Per @gafter:

The benefits of this proposal do not overcome the drawbacks in terms of language complexity. It is unlikely to ever have a high enough benefit-for-cost to make us prefer it over many other things we could do in this release or many releases into the future.

However, as mentioned at #205 (comment) there seems to be a decent amount of recurring interest in such an operator so there is a community prototype.

@gafter gafter added this to the 2.1 milestone Sep 13, 2016
@gafter gafter self-assigned this Sep 13, 2016
@gafter
Copy link
Member

gafter commented Sep 13, 2016

@HaloFour makes me eat my words.

@alrz
Copy link
Member

alrz commented Sep 13, 2016

This would probably make more sense along with #1276, so that ?. produces an lvalue.

x?.P = y;
if (x != null) x.P = y;

x?.P ??= y;
if (x != null) if (x.P == null) x.P = y;

@orthoxerox
Copy link
Contributor

@alrz I find ??= rather clear in its meaning while ?. lvalues look very confusing.

@alrz
Copy link
Member

alrz commented Sep 13, 2016

@orthoxerox they wouldn't be the same thing though the use cases are kinda similar.

@orthoxerox
Copy link
Contributor

I understand that, but the effect of x?.P?.Q = y; is not immediately obvious, it feels an annoying shorthand like while (*dst++=*src++);. Maybe I will change my mind when it becomes as idiomatic as the latter example.

@HaloFour
Copy link

@alrz

I'd be concerned about the subtleties of how that would be implemented. For example:

// is the method called even if x is null and the result simply discarded?
x?.P = SomeComplexCalculation();

// are there any assignments if x or y are null?
x?.P = y?.P = z;

Although I guess you could argue that assignment to a property isn't really any different from invoking a method:

x?.P = y;
// same as:
x?.SetP(y);
// same as:
if (x != null) { x.SetP(y); }

@alrz
Copy link
Member

alrz commented Sep 13, 2016

@HaloFour Beyond the simple case p ?= F() which can be translated to p ?? (p = F()) in an expression context, those concerns are also associated with the ?= operator.

x ?= y ?= F(); // as a statement
var r = x ?= y ?= F(); // as an expression

How these should be translated? I do prefer lazy evaluation of the right-hand-side, but it would be weird if y doesn't get initialized if x wasn't null!

PS: I like ?= operator better as we have |= which behaves like an = and || for booleans.

@dsaf
Copy link

dsaf commented Sep 14, 2016

This promotes usage of mutability and null.

@DavidArno
Copy link

DavidArno commented Sep 14, 2016

@dsaf,

You summarised my dislike of this proposal far more succinctly than I was going to. 😄

@alrz
Copy link
Member

alrz commented Sep 18, 2016

This promotes usage of mutability and null.

I disagree. You can't remove them either and some operations essentially need null and/or mutability, e.g. lazy initialization or caching. And since C# is not a pure functional language these patterns are pretty common (because you don't have the m-word to handle state). I'd argue that there should be some mechanism to manage mutability and null instead of discouraging them, namely, #5032 and #7626.

@Joe4evr
Copy link

Joe4evr commented Sep 18, 2016

some operations essentially need null and mutability, e.g. lazy initialization

It is actually possible to have your proverbial cake and eat it too, by utilizing Lazy<T>. The people over at Microsoft have already worked hard on making that class mutable once and thread-safe, so you don't have to.

Yes, it's a little more typing if you want to use it everywhere right now. Yes, there have been suggestions to add eg. a lazy keyword for auto-properties to make the compiler emit a Lazy<T> backing field (and @alrz himself even suggests this could be covered by Replace/Original+a marker Attribute, though his example uses ?? instead, which may or may not be thread-safe).

@alrz
Copy link
Member

alrz commented Sep 18, 2016

By "lazy initialization" I meant any initialization that occurs after construction (you don't always have access to the context from which the value is initialized), but sure, you could do it with a simple null check. More to the point, this operator is just a syntactical sugar which targets readability and conciseness. Anyways, I think the two proposals (#13737 and #1276) are complimentary and are more helpful together.

@jnm2
Copy link
Contributor

jnm2 commented Sep 22, 2016

I strongly dislike Lazy<T> and never want to see it integrated as the only option for a lazy keyword.
It's definitely not for every situation. If your class is single-threaded by design, as all are unless you're doing something special, ??= is optimal.
See https://twitter.com/nick_craver/status/722040083944235008 too. 😆

@gafter
Copy link
Member

gafter commented Mar 10, 2017

This is now being tracked at dotnet/csharplang#34

@gafter gafter closed this as completed Mar 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants