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 th
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
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)
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.
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 int
s 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.
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 */ }
&& 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.