csharplang icon indicating copy to clipboard operation
csharplang copied to clipboard

Champion: "&&= and ||= assignment operators"

Open gafter opened this issue 7 years ago β€’ 33 comments

  • [ ] Proposal added:
  • [ ] Discussed in LDM (2018-07-16)
  • [ ] Decision in LDM
  • [x] Rejected
  • [ ] Spec'ed

gafter avatar Jul 16 '18 23:07 gafter

Rocket science.

asyncawaitmvvm avatar Jul 17 '18 19:07 asyncawaitmvvm

@asyncawaitmvvm

Sorry, but this comment is the drop in the bucket that gets you banned. As I told you a week ago, I don't like banning but in the end we want to focus on having a constructive discourse with the community. We can hide your comments, but they have become a distraction we don't need.

terrajobst avatar Jul 17 '18 21:07 terrajobst

if( val != null &&= "some value"){ // do stuff } is this if statement a use case for the "assignment operators" feature?

koddek avatar Sep 27 '18 02:09 koddek

Your sample looks like it's trying to do an equality check, not an assignment. It would not be part of assignment operators if it is not an assignment.

yaakov-h avatar Sep 27 '18 03:09 yaakov-h

Here's an example of use - at least as far as I understand the proposal.

Since the right-hand side won't be evaluated once result is false, the Validate() function shown doesn't do any more work than necessary.

public class CreateProfileView
{
    private string _userName;
    private string _password;
    private string _passwordConfirmation;
    
    // ...
    
    private bool Validate()
    {
        bool result = string.IsNullOrWhiteSpace(_userName);
        result &&= string.IsNullOrWhiteSpace(_password);
        result &&= string.IsNullOrWhiteSpace(_passwordConfirmation);
        result &&= string.Equals( _password, _passwordConfirmation, StringComparison.Ordinal);
        result &&= MeetsRulesForUserNames(_userName);
        result &&= MeetsComplexityRequirements(_password);
        result &&= UserNameIsAvailable(_userName); // Checks our database for active users
        result &&= PasswordHasNotBeenPwned(_password);  // Calls out to the API at haveibeenpwned.com
        return result;
    }
}

(Not that I'd actually write code like this - in the real world, we need actionable messages for the user, not just a simple true or false.)

theunrepentantgeek avatar Sep 27 '18 05:09 theunrepentantgeek

@theunrepentantgeek I don't think that's a very good example since you could just use && in that case without any assignments. Where you cannot do that is if you're doing this in a for loop for example.

Neme12 avatar Sep 27 '18 09:09 Neme12

But on the other hand, if you're doing this in a loop, you should probably just exit early. Actually I'm not convinced this is a good feature at all :smile:

Neme12 avatar Sep 27 '18 09:09 Neme12

&&= would be useful for a loop that does constant-time equality checking to defeat timing attacks πŸ˜‡

A very niche case, though.

yaakov-h avatar Sep 27 '18 09:09 yaakov-h

An example of where I would have used this recently is with the visitor pattern:

class FooVisitor
{
    public bool BarFlag { get; private set; }

    public void VisitNode(Node node)
    {
        BarFlag ||= ExpensiveCheck(node);
    }
}

jnm2 avatar Sep 27 '18 12:09 jnm2

I don't think that's a very good example since you could just use && in that case without any assignments.

@Neme12 You're absolutely right - I was just trying to illustrate the point for @codedek and anyone else who was curious. Though, I've written code like this in cases when I needed to single step in a debugger.

&&= would be useful for a loop that does constant-time equality checking to defeat timing attacks

Since I believe &&= would skip evaluation of the expression if the value is already false, I don't think you'd want to use if your code required constant type. You'd want to use &= instead.

To me the example from @jnm2 is the most compelling one so far.

theunrepentantgeek avatar Sep 28 '18 10:09 theunrepentantgeek

@theunrepentantgeek oh yeah, duh. Whoops πŸ™ˆ

yaakov-h avatar Sep 29 '18 10:09 yaakov-h

Sorry to bother, but could someone please help me understand what exactly this feature solves and why we need it? It seems like unnecessary complication to me, further steepening the learning curve of C#

rakshith-ravi avatar Feb 10 '19 20:02 rakshith-ravi

@rakshith-ravi

Solves compound assignment of binary Boolean expressions. It doesn't complicate the language any more than any of the existing compound assignment operators, which happen to apply to almost every operator except && or || today. If anything, it makes the language more consistent with itself.

HaloFour avatar Feb 11 '19 01:02 HaloFour

@HaloFour so correct me if I'm wrong, but will this:

var a &&= flag;

Roughly expand to this?

var a = a && flag;

Is that what it does? Is my understanding correct?

rakshith-ravi avatar Feb 11 '19 04:02 rakshith-ravi

Minus the β€œvar”.

yaakov-h avatar Feb 11 '19 06:02 yaakov-h

LDM looked at this again today and we don't think this rises to the level of deserving a language change.

gafter avatar Apr 29 '19 19:04 gafter

I should probably share that I've got a spec and a prototype for this feature, in hopes that this feature gets more traction and love

Rekkonnect avatar Oct 22 '21 18:10 Rekkonnect

This could have been useful the other day in a bool property setter. It would have started with value &&= furtherConditions;. (Early return would not have been desirable.)

jnm2 avatar Oct 22 '21 18:10 jnm2

TL;DR question: Is this proposal dead in the water and permanently rejected, if so why?

This proposal was set to REJECTED on April 29, 2019, but I can find no mention of them in the LDM notes of any meeting of April 2019. The operators were discussed on July 16, 2018 as far as I can see, but the only thing mentioned in the notes was that they deserve their own proposal and should thus be splitted out from the ??= proposal.

@MadsTorgersen could you tell me/us why this proposal was rejected?

I started my own discussion (#6827) on this topic (because GitHub search had forsaken me). And was quickly pointed in this direction, and I can't gather from this issue (or the notes I looked through, maybe search is again failing me) why this proposal was rejected. The same was stated by @HaloFour in my short "discussion".

And while @333fred has removed the REJECTED label, as far as I can gather, it was just done so this issue is more easily searchable.

    I'll leave the championed issue open so that it appears when people search, but I'm going to close this one.

Originally posted by @333fred in https://github.com/dotnet/csharplang/issues/397#issuecomment-655085109

So long story short... Why?

synercoder avatar Dec 21 '22 15:12 synercoder

My recollection is that we rejected it because it just wasn't worth the effort. I was one pushing for it, and even I don't think it's that important.

CyrusNajmabadi avatar Dec 21 '22 16:12 CyrusNajmabadi

I have no clue about the effort that goes into these things (just enormously grateful). And I do not wish to trivialize the effort, but to me (an relative outsider) the operator sounds like syntactic sugar over a = a || b;.

But isn't the fact that this issue was raised on at least 3 separate occasions here indicate that there is at least community support for these features? And why shouldn't it hold the same importance as other C# operators that we do have? I mean ??= is currently in the language, and would in my eyes hold the same importance (it was originally in the same proposal). Of all the boolean operators, those 2 are the only 2 that don't have a compound variant of it. I would thus also say that adding support for &&= and ||= would "complete" the language operator wise.

synercoder avatar Dec 21 '22 16:12 synercoder

@CyrusNajmabadi

I was one pushing for it, and even I don't think it's that important.

Maybe worth reconsidering as a community contribution?

HaloFour avatar Dec 21 '22 16:12 HaloFour

But isn't the fact that this issue was raised on at least 3 separate occasions here indicate that there is at least community support for these features?

Definitely. But that still may not be important enough to us. We have literal finate resources. So time spent on this is time not spent on other things. I think we collectively just said it was fast too low to be worth it.

CyrusNajmabadi avatar Dec 21 '22 16:12 CyrusNajmabadi

@CyrusNajmabadi like @HaloFour stated, is it perhaps possible to consider this by way of community contribution? Because @Rekkonnect already said he had made a prototype:"

I should probably share that I've got a spec and a prototype for this feature, in hopes that this feature gets more traction and love

synercoder avatar Dec 21 '22 16:12 synercoder

Possibly. I'll let @333fred weigh in. I know that community PRs are still very expensive for us. It helps with just one part of the costs here, but overall it's still something that will get likely push other work out.

CyrusNajmabadi avatar Dec 21 '22 16:12 CyrusNajmabadi

Unless and until a member of the LDM decides to bring it for retriage, we won't accept pull requests for this feature.

To speak to how much work this feature would require, my ballpark is several hundred hours of engineering time. It's not quite the simplest language feature (that would probably be around 100 engineering hours), but it's also not that bad. It needs:

  • Debate and approval by the ldm. This is ~14 people, meeting for at least an hour (likely several hours, especially when the implementation raises questions not considered in the original specification as it encounters edge cases).
  • Implementation. For a feature like this, probably a week or two of work for a junior engineer. Less for someone very familiar with the area.
  • Review. This is two roslyn developers, putting several hours of work to review the pr(s) implementing the feature. For a junior/external engineer, reviews are not a short process, and we often have to have significant chunks of the approach rewritten by the contributor during review.
  • Min bar IDE work. At a minimum, the ide needs to behave ok in the face of the new feature before merge. A member of the IDE team needs to be a buddy on the feature to help with this (though the contributor is still doing most of the work) to ensure it meets the min bar.
  • More IDE work. Min bar just means "it doesn't crash or make it hard to type". There still needs to be things like formatting options, refactorings, completion adjustments, etc.
  • Test plan review. The compiler team meets (minimum 1 hour for the whole team) to go over the test plan and make sure there aren't any test gaps.
  • Documentation. We work with our docs team to make sure there are basic docs available on the feature, with more complete docs soon to follow.

The list above isn't fully complete, but it's got a lot of it. As you can see, while an external contributor can help with some of it, we're still looking at a significant investment of compiler team time, even for a small feature like this one.

333fred avatar Dec 21 '22 17:12 333fred

Jup... my previous point stands:

I have no clue about the effort that goes into these things (just enormously grateful).

synercoder avatar Dec 21 '22 17:12 synercoder

Unless and until a member of the LDM decides to bring it for retriage, we won't accept pull requests for this feature.

Then my follow-up question would be: how do we get somebody of the LDM to retriage this? By gathering πŸ‘ emojis on this champion?

synercoder avatar Dec 21 '22 17:12 synercoder

@synercoder Give them Something To Believe In by Poison. 🀣

iam3yal avatar Dec 21 '22 23:12 iam3yal

how do we get somebody of the LDM to retriage this

By giving us persuasive examples of how this would improve code enough to be worth the effort. Remember, I said several hundred engineering hours of work above. From my own experience, I've been annoyed at the lack of a &&= maybe 2 or 3 times in the past 6 years, and never been annoyed (that I can recall) at the lack of a ||=. I reach for ??= all the time. There is certainly the possibility that they'd come up more if I had the option available, but I somewhat doubt it. I just don't see many delayed &&s very often.

333fred avatar Dec 21 '22 23:12 333fred