Logical vs. Conditional Logical Operators in C#

J

Jonathan

Hi all,

I'm having an argument with a co-worker about the difference between
the & and && operators when applied to boolean operands in C#. His
point of view is that the expression (false & expr2) might be optimised
at JIT-time and the second expression will not be evaluated. In my
opinion this would break the contract of the C# language if the JIT
compiler were to remove the call to expr2 entirely. I'm not saying that
it's good programming practice to depend on the side effects of expr2's
evaluation, all I'm saying is that it just feels _right_ to know that
both sides of the logical expression were evaluated.

I'd really appreciate any input from some of the CLR gurus out there.
Is there a difference between these operators in IL? Might a JIT
compiler conceivably shortcut the evaluation? Any other things I
missed?

Thanks,

Jono
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

When using the && operator the compilier uses short circuit logic, e.g.
it the first oparand is false, the second one is not evaluated. This can
be used in statements like:

if (str != null && str.Length != 0) ...

This is safe, as the second operand is not evaluated it the reference is
null. If both operands were evaluated, the second would throw an
NullReferenceException if the reference was null.

When using the & operator, both operands are always evaluated.
 
J

Jon Skeet [C# MVP]

Jonathan said:
I'm having an argument with a co-worker about the difference between
the & and && operators when applied to boolean operands in C#. His
point of view is that the expression (false & expr2) might be optimised
at JIT-time and the second expression will not be evaluated. In my
opinion this would break the contract of the C# language if the JIT
compiler were to remove the call to expr2 entirely. I'm not saying that
it's good programming practice to depend on the side effects of expr2's
evaluation, all I'm saying is that it just feels _right_ to know that
both sides of the logical expression were evaluated.

I'd really appreciate any input from some of the CLR gurus out there.
Is there a difference between these operators in IL? Might a JIT
compiler conceivably shortcut the evaluation? Any other things I
missed?

Both sides are evaluated with &. As you say, only evaluating one side
would be breaking the language spec. (If the JIT notices that it's
completely without side-effects, it could do some optimisation - but
you'd have to look at the generated code to know for sure.)

With &&, it's guaranteed that the RHS won't be evaluated if the LHS is
false.

This (and its equivalent for "or") allows for things like:

if (x==null || x.Length==0)

to be safe.
 
L

Lebesgue

JIT compiler will not shortcut the evaluation, C# compiler will - for both
&& and &, it will not even compile the if clause.

void Test(bool b)
{
if (false & b)
{
Console.WriteLine("foo");
}
else
{
Console.WriteLine("boo");
}
}

gets compiled by csc into the following IL:

..method private hidebysig instance void Doo(bool b) cil managed
{
.maxstack 8
L_0000: ldstr "boo"
L_0005: call void [mscorlib]System.Console::WriteLine(string)
L_000a: ret
}
 
R

Richard Blewett [DevelopMentor]

Jonathan said:
Hi all,

I'm having an argument with a co-worker about the difference between
the & and && operators when applied to boolean operands in C#. His
point of view is that the expression (false & expr2) might be optimised
at JIT-time and the second expression will not be evaluated. In my
opinion this would break the contract of the C# language if the JIT
compiler were to remove the call to expr2 entirely. I'm not saying that
it's good programming practice to depend on the side effects of expr2's
evaluation, all I'm saying is that it just feels _right_ to know that
both sides of the logical expression were evaluated.

I'd really appreciate any input from some of the CLR gurus out there.
Is there a difference between these operators in IL? Might a JIT
compiler conceivably shortcut the evaluation? Any other things I
missed?

Thanks,

Jono

Well empirically && short circuits and & doesn;t (just tested it in VS2005).

If it makes the call in one situation it would be madness to sometimes not
make the call in others due to JIT optimization. The behavior of the code
would be non-deterministic depending on the mood of the JIT.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk
 
B

Bruce Wood

It's the other way around.

false && expr2 is guaranteed never to evaluate expr2, just as
true || expr2 is guaranteed never to evaluate expr2.

whereas

false & expr2 is guaranteed to always evaluate expr2, just as
true | expr2 is guaranteed always to evaluate expr2.

The && and || operators are referred to as using McCarthy evaluation
(for us old-timers) or more recently "short-circuit" evaluation. In
general the && and || forms are preferred, and it is common C, C++, and
C# idiom to say things like:

if (myObject != null && myObject.BoolProperty)
{
... do something ...
}
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

The & operator does not use shortcut. What you demonstrate is compiler
optimization when one of the operands is a known value.
JIT compiler will not shortcut the evaluation, C# compiler will - for both
&& and &, it will not even compile the if clause.

void Test(bool b)
{
if (false & b)
{
Console.WriteLine("foo");
}
else
{
Console.WriteLine("boo");
}
}

gets compiled by csc into the following IL:

.method private hidebysig instance void Doo(bool b) cil managed
{
.maxstack 8
L_0000: ldstr "boo"
L_0005: call void [mscorlib]System.Console::WriteLine(string)
L_000a: ret
}

Jonathan said:
Hi all,

I'm having an argument with a co-worker about the difference between
the & and && operators when applied to boolean operands in C#. His
point of view is that the expression (false & expr2) might be optimised
at JIT-time and the second expression will not be evaluated. In my
opinion this would break the contract of the C# language if the JIT
compiler were to remove the call to expr2 entirely. I'm not saying that
it's good programming practice to depend on the side effects of expr2's
evaluation, all I'm saying is that it just feels _right_ to know that
both sides of the logical expression were evaluated.

I'd really appreciate any input from some of the CLR gurus out there.
Is there a difference between these operators in IL? Might a JIT
compiler conceivably shortcut the evaluation? Any other things I
missed?

Thanks,

Jono
 
L

Lebesgue

What I did was answering the question. The question was whether JIT
optimizes false & expr2, and compiler optimization gets involved in this
case, as I've written.

I would understand if the OP meant something different from what he had
written (e.g. "is expr2 evaluated if I type if (expr1 & expr2), if expr1
gets evaluated to false?"), but it was obvious to me that he asked about
evaluating & operator application to known "false" value and expression.

Göran Andersson said:
The & operator does not use shortcut. What you demonstrate is compiler
optimization when one of the operands is a known value.
JIT compiler will not shortcut the evaluation, C# compiler will - for
both && and &, it will not even compile the if clause.

void Test(bool b)
{
if (false & b)
{
Console.WriteLine("foo");
}
else
{
Console.WriteLine("boo");
}
}

gets compiled by csc into the following IL:

.method private hidebysig instance void Doo(bool b) cil managed
{
.maxstack 8
L_0000: ldstr "boo"
L_0005: call void [mscorlib]System.Console::WriteLine(string)
L_000a: ret
}

Jonathan said:
Hi all,

I'm having an argument with a co-worker about the difference between
the & and && operators when applied to boolean operands in C#. His
point of view is that the expression (false & expr2) might be optimised
at JIT-time and the second expression will not be evaluated. In my
opinion this would break the contract of the C# language if the JIT
compiler were to remove the call to expr2 entirely. I'm not saying that
it's good programming practice to depend on the side effects of expr2's
evaluation, all I'm saying is that it just feels _right_ to know that
both sides of the logical expression were evaluated.

I'd really appreciate any input from some of the CLR gurus out there.
Is there a difference between these operators in IL? Might a JIT
compiler conceivably shortcut the evaluation? Any other things I
missed?

Thanks,

Jono
 
P

Peter Morris [Droopy eyes software]

My question is, why would you want to evaluate more than you need to? If
the whole expression cannot possibly evaluate to true, then why would you
want to spend CPU cycles evaluating the rest of the expression?

If you want to ensure expr2 is called then you should explicitly call it
before the if statement

bool expr2Result = expr2;
if (false && expr2Result)......


I think that is much more clear than

if (false & expr2)

especially as someone may come along at a later date and change it to &&
because they think they are "optimising" the code!



Pete
 
B

Bruce Wood

The question was whether JIT optimizes false & expr2, and compiler optimization gets involved in this case, as I've written.

No it does not. The following code:

class Start
{
private static bool SideEffectMethod()
{
Console.WriteLine("Hello from SideEffectMethod");
return true;
}

[STAThread]
static void Main(string[] args)
{
if (false & SideEffectMethod())
{
Console.WriteLine("Hi here.");
}
}
}

Produces the output, "Hello from SideEffectMethod", which it would not
if the expression were optimized by the compiler.

Changing the & to a && results in no output.
 
L

Lucian Wischik

Jonathan said:
I'm having an argument with a co-worker about the difference between
the & and && operators when applied to boolean operands in C#. His
point of view is that the expression (false & expr2) might be optimised
at JIT-time and the second expression will not be evaluated. In my
opinion this would break the contract of the C# language if the JIT
compiler were to remove the call to expr2 entirely.

I reckon that expr2 WILL possibly be optimised-away so long as the
JITter can tell that expr2 has no side effects.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top