77

We have equivalent assignment operators for all Logical operators, Shift operators, Additive operators and all Multiplicative operators.

Why did the logical operators get left out? Is there a good technical reason why it is hard?

Antonio
  • 19,451
  • 13
  • 99
  • 197
George Duckett
  • 31,770
  • 9
  • 95
  • 162

3 Answers3

53

Why did the logical operators get left out? Is there a good technical reason why it is hard?

They didn't. You can do &= or |= or ^= if you want.

bool b1 = false;
bool b2 = true;
b1 |= b2; // means b1 = b1 | b2

The || and && operators do not have a compound form because frankly, they're a bit silly. Under what circumstances would you want to say

b1 ||= b2;
b1 &&= b2;

such that the right hand side is not evaluated if the left hand side does not change? It seems like only a few people would actually use this feature, so why put it in?

For more information about the compound operators, see my serious article here:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/compound-assignment-part-one

and the follow-up April-Fools article here:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/compound-assignment-part-two

Pang
  • 9,564
  • 146
  • 81
  • 122
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 44
    I've wanted short-circuiting compound assignment before. No one uses them because they don't exist. See also http://stackoverflow.com/questions/2324549 which gives a number of example use cases. – Ben Voigt Jun 14 '11 at 15:50
  • 4
    Can you please explain the "only a few people will use it, it adds complexity, and there is an existing way to accomplish the stated goal anyway" argument to some (not to be named) members of my company? I've tried and apparently failed. :) – Ed S. Jun 14 '11 at 16:00
  • 14
    re: "Under what circumstances would you want to say `b1 ||= b2; ...`"? These circumstances: I have an array of elements and need to test some condition for each element, so I loop through the array and create a 'running total' of sorts: `result=TRUE; for (i...) {result &&= a[i];}` Or I might want to do a running total of 'OR's. In fact, I had just such a situation in a project I'm working on now. Is that so silly? – daver Aug 10 '13 at 14:59
  • 1
    To Slipp D. Thompson: your comments, as well as others in this conversation, were deleted by moderators in response to multiple flags from the community. This conversation was not going in a very constructive or positive direction. Eric has no ability to delete comments himself. – Brad Larson Mar 02 '16 at 20:38
  • 2
    @daver: Sorry I missed your comment when it was posted. Though that seems plausible, there are more efficient idioms that you could use for those scenarios. `array.All(x=>x)` is maybe a little hard to read, but it has the same semantics as the iterated `&&` operation you propose **and** it bails out when the first false is detected rather than continuing to iterate over the array trying to make the expression true. Similarly for `array.Any(x=>x)` for iterated `||`. – Eric Lippert Mar 02 '16 at 20:45
  • @daver: Moreover: the point of `&&=` over `&=`, which you already have, would be to avoid the cost of the right hand side when the left hand side is false. Does that really avoid a cost in your case? You are trading a test *and a branch* in exchange for skipping an array read -- cheap -- and a logical and -- super cheap! This would be in many cases *larger, slower code*. Larger code means more frequent cache misses, more branches means more opportunities for the branch predictor to get it wrong. More basic blocks means the jitter has more work to do. Not worth it. – Eric Lippert Mar 02 '16 at 22:24
  • I suspect I fall squarely in the "only a few people" category, but I want to perform a sequence of expensive (in time and money) hardware operations, only if the previous operation succeeded. In this case &&= would be very useful. Though I guess short circuiting with an exception is just as good. – Chris Petheram Sep 12 '17 at 10:04
  • 29
    I strongly disagree about the sillyness :) I just had the following requirement: `isAdmin |= IsGroupAdmin(); isAdmin |= IsCompanyAdmin()`, where `IsGroupAdmin()` and `IsCompanyAdmin()` are expensive methods that require database-Selects. In these cases I cannot use `|=` obviously for performance reasons and have to use `isAdmin=isAdmin ||...` and a `||=` would really help. – Ole Albers Oct 06 '17 at 12:29
  • 21
    `&&=` and `||=` are far from silly. When the RHS is expensive, they are very useful. Whether that's a db lookup or a URL fetch or a regex match or ... there are tons of serious use cases for such an operator. (`??=` also falls into the same category - if it's null, then do this big expensive operation to determine a value). I have a hard time taking someone seriously who thinks this is silly. – Tanktalus Apr 04 '18 at 16:42
  • For me these 2 are validly complemental. Exactly in the way it was said by @EricLippert (_ … such that the right hand side is not evaluated if the left hand side does not change?_). E.g `userHasFeatureEnabled &&= !DidAdminRemovedUsersFeatureRight()`. – Yarl Sep 04 '20 at 13:41
2

maybe just use

isAdmin = isAdmin || IsGroupAdmin()

I guess it is partially because a ||= b is kind of confusing because there might be two versions of the implementation: a = a || b, or a = b || a. And they act differently because the right-hand side of the expression is sometimes not evaluated.

0

In the C# there is a double question mark operators (null-coalescing operators).

There are two forms of it:

a = b ?? c;

and

a ??= b;

The first one evaluates as: a = b != null ? b : c; The second one - is what you are asking: a = a != null ? a : b;

Sure, at the place of any of these vars might be complex expressions.

Here is a reference: null-coalescing operators

Arsenii
  • 655
  • 1
  • 8
  • 20