5

here is a tl;dr

I come from a C++ background. && is suppose to check if left side is true and right side is true. what does & have anything to do with this? Why is it being used in the && logic?


I couldnt understand http://msdn.microsoft.com/en-us/library/aa691312%28v=vs.71%29.aspx and asked a question. It took me quite a while to understand and accept this answer. I had to do a lot of follow up reading How does operator overloading of true and false work?

The operation x && y is evaluated as T.false(x) ? x : T.&(x, y)

Why on earth is it doing this? if the false overload returns true and the true operator returns true then y is not evaluated at all. WTF!!!!

I still cant understand it. Because of this being so weird to me it took me a while to understand the answers in the other question. In C# v = 1 && 2; does not work bc you cant do && on ints. In C this returns true (heres code/example http://codepad.org/9iCaqzQ2). If we follow the operation rule above for this we would do

(using 1 && 2)

  • Int.False(1) is false
  • 1 & 2 (== 0)
  • Int.True(0) (== false)

This would get you the wrong results.

So... What is the reasoning for C# doing the && (and ||) operator(s) the way it does.

Community
  • 1
  • 1
  • 4
    Please take some time to improve the writeup. It's impossible to understand what you want to ask. – Jon Mar 05 '11 at 11:26
  • @archer That's a natural thing to do. If a language departs from what older languages does it usually has a reason for doing so. Being different for the sake of being different is usually not a good idea. And knowing why something works like it does is almost as important as knowing how something works. – CodesInChaos Mar 05 '11 at 13:22
  • @CodeInChaos: Exactly CodeInChaos. I wonder why your the ONLY one who told me why something was actually different instead of saying 'no your doing it wrong' and 'wtf are you talking about' -_-. I was so frustrated with everyone. –  Mar 05 '11 at 13:26
  • I learned c after knowing pascal. Pascal has only a single `and` operator which is logical(and short circuiting) on booleans, and binary on integers. So when switching to c I had something like the opposite problem of yours. Why the hell does c have no booleans and uses two kinds of `and` instead? You can get used to something so much that you stop questioning the why. If you start from the definition that `&&` is the short-circuiting and then your question makes no sense, if you start with logical vs binary it does. – CodesInChaos Mar 05 '11 at 13:46
  • 1
    And then there is the Engineer vs Scientist, "How?" vs "Why?". I for one value the "Why?" much higher. If you know the why the how usually becomes trivial. The flip side of this is that I have a hard time using something I don't really understand. – CodesInChaos Mar 05 '11 at 13:49
  • +1 :). Now i am considering only having & in my language. No &&s. Like... C# really doesnt need an & now that i know this reason. (maybe it does, i still need to think about it) –  Mar 05 '11 at 13:57
  • Having `&` short circuit on bools is something I'd rather avoid since it'll surprise many programmers. I'd add a short circuiting `&&` on bools, but wouldn't support `&&` on any custom types. – CodesInChaos Mar 05 '11 at 14:11

7 Answers7

8

&& is defined as a short-circuiting operator; if the first operand evaluates false, it is demanded to short circuit there and not evaluate the right hand side. What else would you expect it to do? This allows checks like if(arg != null && arg.Foo) {...} etc.

Your question basically says "if I write an incorrect implementation of a true/false operator, bad things happen"... so; don't do that! either don't write a true/false operator at all, or if you do; do it right...

There are also &and | which do not short-circuit.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    This is where i am confused. Lets say i wrote this for int and want to return false when evaluating 0. I am to return true on the false operator? which is why in my example steps above i return false in the false operator on the first step (int.false(1), cause its true. I assume when both true and false returns false it is considered null.) –  Mar 05 '11 at 11:34
  • @acidzombie24 well, if you confuse bitwise and boolean logic, bad things happen... and? – Marc Gravell Mar 05 '11 at 11:36
  • I'm still confused. ok how about this. I come from a C++ background. && is suppose to check if left side is true and right side is true. what does & have anything to do with this? Why is it being used in the && logic –  Mar 05 '11 at 11:38
  • It will only check if *both* sides are true if the left hand side is true. If the left side is false it returns false and doesn't check the right side... – TimCodes.NET Mar 05 '11 at 11:41
  • 1
    @acidzombie - to be specific, `&` as a bitwise operator doesn't support the necessary condition to satisfy boolean logic, i.e. you don't know that `x==true` and `y==true` means `x&y==true`, with `1` and `2` as counter examples. – Marc Gravell Mar 05 '11 at 11:48
  • @Marc Gravell the OP problem is likely that if you overload true / false , c# will end up calling & and | , which we normally think of as bitwise operators – nos Mar 05 '11 at 11:48
  • @acidzombie which is why very very (if any) types operate with *both* boolean-logic and bitwise-arithmetic semantics. – Marc Gravell Mar 05 '11 at 11:49
  • @nos: Correct. And In C writing 1 && 2 returns true which i expect. In C# it calls the logical & op which i do 1&2 to create a new int 0 which is now NOT TRUE (its false). Which... is a big WTF for me bc my understanding is the && checks if both sides are true. The & op shouldnt play any role which is what my question is about. Why is it playing a role in C#/.NET –  Mar 05 '11 at 11:52
  • @Marc: Sorry i dont understand your comment. I am not saying && should use the & operator. The quoted text is from msdn and how the && operator works in C#. Which i am questioning because it makes no sense to me. –  Mar 05 '11 at 11:55
  • Your misunderstanding comes from the fact that in C && does the same thing that & does in C#. && in C# is just a control structure see here http://en.wikipedia.org/wiki/Logical_conjunction I don't understand what you're getting worked up about and downvoting answers that are answering your question? – TimCodes.NET Mar 05 '11 at 12:05
  • @Chimoo: I didnt DV them and even said i liked one that got DV. Anyways, i looked at the link and it seems to be telling me what i already know about logical gates. If bit one (or left side) is set/true and the right side is also set/true then the result is true. THIS IS NOT what is happening in C# –  Mar 05 '11 at 12:09
  • That wasn't the bit I meant you to read, you were meant to read the bit that says "Some programming languages have a related control structure, the short-circuit and, written &&, and then, etc" which Marc has told you about – TimCodes.NET Mar 05 '11 at 12:11
  • @Marc: From this answer to a new question http://stackoverflow.com/questions/5203770/why-is-1-2-in-c-false i now think you are saying & is either logical or boolean but not both and && is a short circuited logic or boolean but it can not be logical and short circuited boolean? That other answer makes sense. I think you are now saying this bc you said "which is why very very (if any) types operate with both boolean-logic and bitwise-arithmetic semantics" which didnt make sense to me –  Mar 05 '11 at 12:34
  • @acidzombie that is because you are assuming C# always takes the same choices as C; it doesn't. – Marc Gravell Mar 05 '11 at 15:33
  • @Marc: Correct, It took quiet a while for someone to point out && is the same as & but short circuiting and only one preson (codinginchaos) realized i was asking why it worked the way it does and told me the reasoning behind that decision. And explain why i was confused (i didnt realizing they are meant to be same and not logical vs bitwise as i thought) –  Mar 05 '11 at 16:47
3

C# is more type safe then C++.

Firstly & is overloaded, there are two versions one is the bitwise AND which operates on two integral types (such as int, long) and returns the result of AND each bit from the first argument with the corresponging bit in the second argument. For example 0011 & 1010 == 0010.

The second overload is logical AND which operates on two boolean types (bool), it returns true if and only if both arguments are also true.

Finally you have && which is conditional AND, again it operates two boolean types and returnes true if and only if both arguments are true but it also has the added guarentee that if the first arugment is true the second argument will not be evaluated. This allows you to write things like if(arr != null && arr.Length > 0)... without the short-circuiting behaviour this would give you a null reference exception.

Rules for | and || are similar, | is overloaded for bitwise and logical OR, and || is the conditional OR.

The reason your possible getting confused with C++ behaviour is that integral types are implicitly convertable to bools in C++, 0 is false and anything else is true, so 5 && 5 returns true in C++. In C# intergral types are not implicitly convertable to bools so 5 && 5 is a type error. && and || are also short-circuiting in C++ however, so you shouldn't be suprised at that being the same in C#.

Ibasa
  • 627
  • 4
  • 10
3

As I understand you would prefer a && b being defined as something like ((bool)a)&&((bool)b) instead of what C# uses.

But I think this kind of operator overloading was introduced to support tri-state bools such as bool? and DBBool.

Let's define a few examples for such a type:

With no short circuiting possible:

null && true == null
null && false == false
null || true == true
null || false == null

With short circuiting possible:

false && null == false
true || null == true

The basic idea here is to treat null as unknown value and return null if the result is undetermined and a bool if the result doesn't change no matter what you put into the null argument.

Now you want to define a short circuiting logical and and or on this type. If you do that using the C# true and false operators, both of which return false on a null argument you get the desired behavior. With a c like behavior you don't.

The C# designers probably didn't care about logical and/or on integers like in your example. Integers are no boolean values and as such should not offer logical operators. That bool and integer are the same thing is one of c's historic properties that a new language doesn't need to mirror. And the distinction of bitwise vs logical operators on ints only exists in c due to c's inability to distinguish booleans and integers. This distinction is unnecessary in languages which distinguish these types.

Calling & a bitwise operation is misleading in C#. The essence of && vs & isn't logical vs bitwise and. That isn't determined by which operator you use, but by which types you use. On logical types (bool, bool?, DBBool) both operators are logical, and on integer types & is bitwise and && doesn't make sense, since you can't short-circuit on integers. The essence of && vs & is that the first short-circuits and the second doesn't.

And for the cases where the operators are defined at all this coincides with the c interpretation. And since && isn't defined on integers, because that doesn't make sense with the C# interpretation of && your problem of how && is evaluated on integers does not exist.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • Excellent answer. Once again i know exactly why they did this. That makes complete sense. Although, i do want to add `null && false == false`strikes me as odd. As well as `null || false == null`. I would have swapped them (N&&F=N, N||F=F) –  Mar 05 '11 at 13:19
  • 1
    @acid Put in both `true` and `false` instead of `null`. In the `&&` example you get false in both cases. So you can safely say the result if false. In the `||` example you get `true` once and `false` once. So the result is undefined and thus `null`. So it makes sense this way. – CodesInChaos Mar 05 '11 at 13:24
  • Doing your true&&false thing, its actually pretty logical. Good example. I still need an example of why someone would use this feature. Right now i am designing a language and i outright ban this. -edit- hmm. I can see why null||true is true. But i'm unsure why null||false = null. In my example i put true>false>null but in C# its true>null>false. in a manner of speaking –  Mar 05 '11 at 13:42
  • `true||false==true` and `false||false==false` So you don't know what the result of `unknown||false` is. So you need to use `null` which indicates an unknown result. You might want to look into lifted operators on `Nullable` which have similar properties. The idea is to work with unknown values(represented by `null`) just like you'd work with normal values. And at least it allows us to overload `&&` in a short-circuiting way. Unlike C++ where `&&` short-circuits on built in types but doesn't on user defined types. – CodesInChaos Mar 05 '11 at 13:54
  • How would i use this code anyways? Could you give me an example where null&&false==false is desirable? or null||false=null desirable? I checked in my language and right now if you do null && anything you get a null exception. I never actually needed null && or || in code and i would like to consider not throwing a null exception. I wrote this code maybe 30mins ago, it says i cant do null && or || at all. How would one use the null && boolval features in C# without getting a compile error? Even bool? v=val; v&&false doesnt work. http://www.pastie.org/1636054 –  Mar 05 '11 at 13:54
  • I think the DBBool type defined in this example exhibits the behavior I described: http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx I thought `bool?` worked like this too, but it seems like they only lift the non short-circuiting `&` but not `&&`. – CodesInChaos Mar 05 '11 at 14:09
  • @acid I was surprised that your code doesn't compile. So I've asked a question why that's the case: http://stackoverflow.com/questions/5204366/why-are-there-no-lifted-short-circuiting-operators-on-bool – CodesInChaos Mar 05 '11 at 14:57
  • I see no reason short-circuiting semantics couldn't be reasonably applied to integers. When evaluating `f() & g()` [both functions return `int`], if `f()` yields zero, the value of `g()` can't affect the result. If integers defined `op_false` to mean the value was zero, `f() && g()` could skip the evaluation of `g()` when `f()` yielded zero. – supercat Jun 02 '14 at 17:26
0

These operators become easier to understand if you translate them into VB.Net, as follows:

&& = AndAlso: IF foo IsNot Nothing AndAlso foo.bar=1 then <>...

|| = OrElse: If foo Is Nothing OrElse foo.bar=0 then ...<>...

That way when you read them in English you really get the idea of what they are trying to acheive.

Jon Egerton
  • 40,401
  • 11
  • 97
  • 129
  • This help but i still dont understand. Lets say foo is class int and the values i am ANDing is 1 and 2. How would it work? also, i still have no idea why & is being used in the && operator. In C && means left side AND right side must both be true. It has nothing to do with a logical & in C. –  Mar 05 '11 at 11:47
  • Not sure why these answers are getting -ve votes - seems a little harsh! What do you mean ANDing 1 and 2? – Jon Egerton Mar 05 '11 at 11:58
  • Author of question just can't ask clearly and decresing reputation to all, who trying to help but can't undestand him... – kyrylomyr Mar 05 '11 at 12:23
0

A perhaps overlooked part of the question here is why doesn't C# automatically cast integers to booleans?

Automatically casting ints to bools (using the rules of C/C++) allow for a accidentally assigning instead of comparing two values. The C# language designers probably wanted to avoid this...

int a, b;
if(a == b)
    { /* They are equal, so execute this code... */ }

if(a = b)
    { /* Were they actually equal? Dunno, but they are now... */ }

or

while(a = b)
    { /* Eternal loop */ }
Arjan Einbu
  • 13,543
  • 2
  • 56
  • 59
-1

If you want both sides to be evaluated you need to use the 'standard' & and | operators. Usually you do want the && and || operators though for efficiency

cusimar9
  • 5,185
  • 4
  • 24
  • 30
  • You cant overload && which i mentioned ealier today http://stackoverflow.com/questions/5202862/why-cant-i-overload-the-operator-in-c-but-i-still-can-use-it. But isnt && suppose to check if left side is true and right side is true? what does & have anything to do with this? –  Mar 05 '11 at 11:36
  • See http://msdn.microsoft.com/en-us/library/2a723cdk(v=vs.71).aspx *The conditional-AND operator (&&) performs a logical-AND of its bool operands, but only evaluates its second operand if necessary.* – cusimar9 Mar 05 '11 at 11:57
-2

If x == false, then x && y will be always false -> no need to see value of y. If x == true, then x & y happens. This gives you optimized logic operations.

For int it will be something like: T.false(x == true) ? x : T.&(x == true, y == true)

kyrylomyr
  • 12,192
  • 8
  • 52
  • 79
  • My question is confusing. Try reading it again or reading the comments i made on the other two answers. I am not asking about the logics but why the operators are working weirdly –  Mar 05 '11 at 11:37
  • They works weirdly, because you trying to use them weirdly. Ints isn't a true/false value. So you can't use logic of C# to ints of C++. And read edit of my answer. – kyrylomyr Mar 05 '11 at 12:04