2

edit: My main question now is why these two operators need to be overloaded to use the && and || operators. Wouldn't the short-circuit operators take the true or false values of the objects and compare those? Where in the use of the && and || operators is | and & used?

I'm reading C#, the complete reference, and I'm quite confused about the | and & operators. I'm used to them being bitwise operators that compare the bits of two integers, but they're explained as the original logical operators, to which && and || are the short-circuit versions that stop testing values when the statement is definitely going to be a certain value.

Does this mean that the two operators have multiple uses, or that C# does do some behind the scenes type casting?

Also, when using the && and || operators on a class, why do | and & have to be overloaded? Why can't just the true and false values for a class be overloaded?

mowwwalker
  • 16,634
  • 25
  • 104
  • 157
  • These operators are pretty much the same in *all* languages: http://en.wikipedia.org/wiki/Bitwise_operation – Brian Roach Jan 08 '12 at 07:20
  • `&` and `|` have a double meaning from what I've found in that they can be bitwise operators (depending on their usage) or conditional operators (similar to `&&` and `||`) where they mean `and` and `or` where as `&&` is equivalent to 'andalso' and `||` is 'orelse'. [This](http://visualbasic.about.com/od/quicktips/qt/vbnetlogop.htm) article has a good explanation. Basically they are used to determine *how* your conditions are evaluated. – M.Babcock Jan 08 '12 at 07:22
  • C# operators: http://msdn.microsoft.com/en-us/library/6a71f45d(v=VS.100).aspx – Mitch Wheat Jan 08 '12 at 07:25
  • @M.Babcock: That's because VB.NET is backwards compatible with VB 6, which only had `&` and `|`, and thus used them as both bitwise and conditional operators. They don't really have a double meaning though; they're still performing bitwise operations. – Cody Gray - on strike Jan 08 '12 at 07:25
  • Why would someone down votes, when Eric Lippert answers. – crypted Jan 08 '12 at 07:25
  • 2
    @Int3ὰ: Because good answers do not make good questions? That's why there are separate vote counts for questions and answers. – Cody Gray - on strike Jan 08 '12 at 07:26
  • [One article](http://www.c-sharpcorner.com/UploadFile/jaishmathews/AndAlsoOrElseOperatorsinCSharp03112006104809AM/AndAlsoOrElseOperatorsinCSharp.aspx) describing what I have also seen. EDIT: Also apparently supported by Eric's answer below. – M.Babcock Jan 08 '12 at 07:26
  • @Cody Gray. The problem with the down vote is, it will go unnoticed if question have too many down votes, by saying that what i mean is If **Eric** answers then there must be something with the question that is not so common. – crypted Jan 08 '12 at 07:34

2 Answers2

14

The | and & operators are bitwise operations on integers and eager logic operators on Booleans. The || and && operators are lazy logic operators on Booleans.

Also, when using the && and || operators on a class, why do | and & have to be overloaded? Why can't just the true and false values for a class be overloaded?

You have a class Foo with an overloaded true and false operator. You wish the && operator on Foo to take two Foos and return a third. Explain how you plan to do so with only the true and false operators.

why do we need eager Boolean logic operators in C#?

In case you want to evaluate the side effects of two Boolean-returning values and apply a logical operation to them.

I don't understand, with the && and || operators, I want a bool returned, not another type.

Then you don't need to overload anything. Just write an implicit conversion operator from Foo to bool and you can use |, ||, & and && to your heart's content.

Just because you don't want to have a && or || operator that returns something other than bool doesn't mean that no one does. Suppose instead of Foo you wish to write a three valued logic operator where the value can be True, False or Neither. You could define & and | and && and || operators on True, False and Neither. Clearly you would not want the operators to return bool; you want them to return True, False or Neither.

What I don't understand is what the | and & operators have to do with the && and || operators.

They're exactly the same operators. The only difference is that the lazy ones don't evaluate the second operand if doing so is unnecessary.

Why must | and & be overloaded to use || and && though?

See the previous question and answer.

The | and & operators take two operands.

Yes, they do. So do the && and || operators.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • why do we need eager boolean logic operators in C#? Never seen these used in C#, and could lead to subtle defects. – Mitch Wheat Jan 08 '12 at 07:26
  • I don't understand, with the && and || operators, I want a bool returned, not another object... – mowwwalker Jan 08 '12 at 07:28
  • +1 for pointing out one of the first things I learned when porting VB.NET/VB6 code to C# – M.Babcock Jan 08 '12 at 07:32
  • What do the && and || operators have to do with anything but booleans? – mowwwalker Jan 08 '12 at 07:34
  • `foo() & bar()` will evaluate both functions before returning a value, `foo() && bar()` will stop at the first false value. I'm not saying that it's *good* to write evaluation code with side-effects, but it's important to understand. – zzzzBov Jan 08 '12 at 07:35
  • I understand that perfectly. What I don't understand is what the | and & operators have to do with the && and || operators... – mowwwalker Jan 08 '12 at 07:38
  • @Walkerneo - Coming from a VB background it is easier to understand. [Here](http://visualbasic.about.com/od/quicktips/qt/vbnetlogop.htm) is an article describing the differences in VB.NET. Basically the `&` and `|` operators roughly map to 'and' and 'or' and `&&` and `||` roughly map to 'andalso' and 'orelse' respectively. – M.Babcock Jan 08 '12 at 07:43
  • @M.Babcock, Yes, I get that. Why must | and & be overloaded to use || and && though? Especially considering the fact that the point of the short-circuit operators is to sometimes only need to test the first condition. The definitions of the | and & take TWO arguments. – mowwwalker Jan 08 '12 at 07:50
  • @Walkerneo - Are you sure the `&` and `|` operators are doing what you expect? From a CLR compliance perspective they can have different meanings so make sure you aren't breaking non-C# use of your code. – M.Babcock Jan 08 '12 at 08:00
  • Alright. I think I'll understand it better when I come across it or see someone's code that uses it. – mowwwalker Jan 08 '12 at 08:13
  • It seems like `T.false(x) ? x : y` and `T.true(x) ? x : y` would work fine for defining `x && y` and `x || y` without using `&` or `|`. Am I missing something? – kvb Jan 08 '12 at 16:51
  • @KVB: Suppose you have four values: BlueTrue, BlueFalse, RedTrue and RedFalse. You wish to define || such that BlueFalse || BlueTrue = BlueTrue, BlueFalse || RedFalse = BlueFalse, RedFalse || BlueTrue = BlueTrue, RedFalse || RedTrue = RedTrue. How do you do so using your scheme? – Eric Lippert Jan 08 '12 at 19:31
  • One problem with short circuiting operators that don't return bool is that `if` takes any type that overloads `op_true`, instead only types that are implicitly convertible to bool, which IMO decreases type safety a bit. – CodesInChaos Jan 08 '12 at 19:53
  • One type commonly used to represent three valued logic is `bool?`. Interestingly it doesn't support short-circuiting logic operators, because for some reason the C# team decided to not lift `op_true`/`op_false`, and to not lift `||`/`&&` directly either. http://stackoverflow.com/questions/5204366/why-are-there-no-lifted-short-circuiting-operators-on-bool – CodesInChaos Jan 08 '12 at 19:59
  • @CodeInChaos: There are two ways to think about it. In a nullable bool, the null can be thought of as meaning "I don't know". So you see A() && B() and A() returns true. Should you evaluate B()? Yes. If A() is false, should you evaluate B()? No. If A() is "I don't know", should you evaluate B()? The only consistent answer is *I don't know if I should evaluate B() or not!* That seems like a bad position to be in. – Eric Lippert Jan 08 '12 at 20:08
  • My logic is, that you should evaluate `B` iff it can affect the result of the expression. The linked question discusses some of these considerations. – CodesInChaos Jan 08 '12 at 20:10
  • 1
    @CodeInChaos: Alternatively, you could say that nullable bool just means "if either operand is null then the result is null". In that case if A() is null then clearly we don't need to evaluate B() -- we know that the result will be null. But now what if A() is false? **Now we need to evaluate B() to know if it is null or not** even when A() was false, which seems like it is going to cause problems when the code author assumed that B() would only be evaluated if A() was true. In short, **it is a big freakin' mess** and the best thing to do is avoid it entirely by not having the feature at all. – Eric Lippert Jan 08 '12 at 20:11
  • @Eric - I didn't mean to imply that all reasonable implementations of `&&` and `||` could be created with only `true` and `false`; I merely wanted to demonstrate that `&` and `|` weren't necessarily needed. Besides, C#'s current approach implies some limitations anyway (e.g. a truthy first argument is always returned by `||` so you can't return some canonical truthy value instead). – kvb Jan 08 '12 at 22:42
0

I didn't expect to be able to find the answer online or else I wouldn't have asked here, but I did manage to, and here's what I have:

From http://msdn.microsoft.com/en-us/library/aa691312(v=vs.71).aspx it says: The operation x && y is evaluated as T.false(x) ? x : T.&(x, y)

In other words, it evaluates the true or false of x and if x is false, returns x, otherwise it returns x & y. This would explain why the two | and & operators need to be overloaded for && and ||, but it doesn't explain why it's not evaluated as:

T.false(x) ? x : T.false(y) ? y : x

If someone can explain why y and x are compared, I would appreciate it.

mowwwalker
  • 16,634
  • 25
  • 104
  • 157
  • As Eric Lippert mentioned in his answer, sometimes `&&` shouldn't return `bool`. For example, trinary logic as found in a database "Yes/No" column: `DBFalse && x` could return false, but `DBTrue && DBNull` must return `DBNull`. – Ben Voigt Jan 08 '12 at 08:06
  • Or in situations where you use `unsafe` – M.Babcock Jan 08 '12 at 08:12