-
Notifications
You must be signed in to change notification settings - Fork 1k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Allow null conditional (?.) operator on left hand side of assignment #2883
Comments
There has been a previous discussion about this at #1800, though that issue is now closed. |
And that issue was deemed to be a dupe of #34. |
I dislike this because the whole line doesn't happen if the LHS is 'null', it is much clearer to wrap this in an |
It makes sense to me, when you have
So, like any conditional access expression, this would naturally fall out as "evaluate what is before the Feels fine and normal to me. it's just something that didn't fall out with how we did the precedence for everything here. |
I've had a brief discussion with @KathleenDollard at Techorama in the Netherlands two weeks ago about this feature. It is not a part of C# 8 right now and we both felt it deserved a feature request of it's own. @Tom01098: I get your point. However I'm also allowed to write: |
@mrjvdveen |
Thanks for your input. I renamed this issue. |
Having improved your title, would you mind removing the "With the introduction of nullable reference types in C# 8 in mind" line in your OP, please? The code, |
Thanks for your input. I have changed the OP. |
I think this has been brought up a couple times before, in short, it comes down to permitting o?.Event += Handler; |
There are other comments there as well. We shouldn't let one bad actor wreck an entire thread. Even if the conversation continues here I think it's good to link the two issues. |
@HaloFour, I agree on having the link here. It documents the history of the discussion on this subject. |
I'd love to be able to write code like this: (dataSource as BindingList)?.ListChanged -= OnListChanged;
dataSource = value;
(dataSource as BindingList)?.ListChanged += OnListChanged; |
Would be nicely consistent with using // works today
foo?.SetBar(CalculateBar());
// maybe?
foo?.Bar = CalculateBar(); |
I like this idea aswell, so I had a look through the Roslyn source to get a feeling for the ammout of work needed to implement this. I've been looking to implement a compiler feature for a while now. I will have a go at implementing this and get back to you with my results. Even if this proposal gets rejected or my implementation proves inadequate, I can use the exercise. |
Have fun! Be aware that PRs for language features that haven't been accepted are usually closed, so don't make a PR. Just leave it in your branch and add a link here. If you need any help, check out the Roslyn gitter. (the amazing) @CyrusNajmabadi is usually happy to help , as am I, just less affectively. Tagging @jaredpar, the Roslyn PM, to see if he thinks there's a chance a PR like this could get accepted. |
Thanks for all the support. @Leemyy : that's awesome. I'm curious to see how this pans out. |
Hmm, while writing the Test cases I stubled upon an interesting corner case: Destructuring Assignments. (left?.X, right?.X) = (1, 1); |
I am thinking that it would be more consistent if it were possible, but maybe there are some aspects of it that I haven't considered? |
My advice is keep it simple for now, and forbid it. If this ever gets championed and bought up on a LDM, it will get discussed. |
I think there's precedent in: var (a, _) = (new object(), new object())
But, as @YairHalberstadt says, leave this for the LDM. |
You're right, this would add too much complexity to implement as part of the Prototype. |
This raises another interesting question: |
@Leemyy |
I'd argue no. |
I am thinking it should not, otherwise compound assignments would make no sense: a?.b += x() * y; Edit: if (a is object)
{
a.b = a.b + (x() * y)
}
else
{
_ = a.b + (x() * y)
} would try to access if (a is object)
{
a.b = a.b + (x() * y)
}
else
{
_ = x() * y
} which would be fine. |
Would this also handle null conditional assignment on set-only properties? using System;
public class MyClass
{
private string property;
public string Property
{
set => property = value;
}
private void MyMethod()
{
// use property
}
}
public static class Program
{
public static void Main()
{
object obj = new MyClass();
//CS0154: The property or indexer 'MyClass.Property' cannot be used in this context because it lacks the get accessor
(obj as MyClass)?.Property = "";
}
} |
The error in that code sample is only produced because, currently, the compiler expects that with Properties with setters should allow |
I'll champion this as well. |
Does this proposal also handle the case of using the |
Is it escaping type safety? something must've gone wrong if you are looking for members in a variable that is null as a consumer. but if you are providing the value you can do this in generic and write once apply to all so it seems to me that it's escaping dealing with the consequences of null in consumer's side it's like shorthand for
regardless I still want this feature to be implemented because I want to be lazy and write unsafe code, what can possibly go wrong, at the end of the day I will be blamed for bugs anyways |
It is not a shorthand for either of those cases. The null-conditional operator for any member access operator ( if (foo is not null)
foo.bar = 5; No exceptions involved, because they're too expensive. No type unsafety either, you always account for
Even with your nullability settings and your strong usage of the |
Maybe we can get rid of null in c# by opt-in feature, instead of giving nullable to everything, and having variables points to nullptr they should have a pointer to a static object that's the default state. I feel annoyed when I forgot to check for null and things break during testing too, only if things were never null I can be happier, I understand I can also take a walk outside and stop returning null in new codes I write it isn't a big deal for me |
This is just not happening. You can use the nullability tooling available since C# 8.0/.NET Core 3.1(?) and respect it like you personally desire. Other than that, if you know your values aren't |
New rules ok |
Such a breaking change is probably never going to happen. I like the idea of having a "default" static object, which from what I assume would have to be constructed by the default instance constructor that will be introduced for that feature. It will have to be triggered in some other way though, like This discussion however should be made in the respective proposal. |
I'd always prefer seeing that something's going wrong instead of having it going havoc silently. That's what If I have code that accepts optional parameters or values, that code has to check for Also, |
In your case I would expect it not work (by nothing happens) since the object isn't null but it's the property that wasn't able to be set |
Any Updates? |
@Xyncgas I've championed this. |
I would love to see this! |
I'm converting this issue to a discussion, as #6045 has the template and proposal. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Consider this code:
I suggest introducing the possibility to write this like so:
Foo?.Bar = "value";
Writing it like this, should do exactly the same as the first example. So if Foo is null, then the assignment never happens.
[Update(jcouv):] Detailed proposal write-up: #6045
The text was updated successfully, but these errors were encountered: