Why are there no ||= or &&= operators in C#?
Solution 1
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://docs.microsoft.com/en-us/archive/blogs/ericlippert/compound-assignment-part-one
and the follow-up April-Fools article here:
https://docs.microsoft.com/en-us/archive/blogs/ericlippert/compound-assignment-part-two
Solution 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.
Related videos on Youtube
George Duckett
This is just here so I get the nice drop-shadow!
Updated on November 11, 2020Comments
-
George Duckett over 3 years
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?
-
Matt Ellen almost 13 yearsIs there a reason why you'd use them?
-
Fosco almost 13 yearsCan you provide an example where they would be useful?
-
Orace over 2 yearsOpened proposition github.com/dotnet/csharplang/issues/1718
-
-
Ben Voigt almost 13 yearsI've wanted short-circuiting compound assignment before. No one uses them because they don't exist. See also stackoverflow.com/questions/2324549 which gives a number of example use cases.
-
Ed S. almost 13 yearsCan 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. :)
-
daver almost 11 yearsre: "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? -
Brad Larson about 8 yearsTo 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.
-
Eric Lippert about 8 years@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 forarray.Any(x=>x)
for iterated||
. -
Eric Lippert about 8 years@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. -
Chris Petheram over 6 yearsI 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.
-
Ole Albers over 6 yearsI strongly disagree about the sillyness :) I just had the following requirement:
isAdmin |= IsGroupAdmin(); isAdmin |= IsCompanyAdmin()
, whereIsGroupAdmin()
andIsCompanyAdmin()
are expensive methods that require database-Selects. In these cases I cannot use|=
obviously for performance reasons and have to useisAdmin=isAdmin ||...
and a||=
would really help. -
Tanktalus about 6 years
&&=
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. -
Yarl over 3 yearsFor 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()
. -
Hagen von Eitzen about 3 yearsNon sequitur. There is
a -= b
and no-one is confused that there might be an implementationa = b - a
instead ofa = a - b