if else ...

  • Thread starter Thread starter Hrvoje Voda
  • Start date Start date
Paul E Collins said:
if (x > 10 || y > 10) // or

if (x > 10 && y > 10) // and

P.

It might be worth mentioning short-circuiting for the conditional statements
above.

if (x > 10 | y > 10) will work fine in this case.

by using || it "short-circuits" the conditional, i.e. it will evaluate x >
10 and only if this is false, y > 10 will be evaluated.

Similarly in if(x > 10 && y > 10), x > 10 will be evaluated and only if tihs
is true, y > 10 will be evaluated.

In the case mentioned it won't make a difference, but be careful when doing
something like:

(1) if (++x > 10 || ++y > 10)

as opposed to

(2) if (++x > 10 | ++y > 10)

In (1) ++y will only be execute if ++x is greater than 10, but in (2) both
++x and ++y will be executed.

I don't to confuse the issue, but I do think it's important to keep this in
mind.
 
Jako said:
It might be worth mentioning short-circuiting for the conditional statements
above.

if (x > 10 | y > 10) will work fine in this case.

by using || it "short-circuits" the conditional, i.e. it will evaluate x >
10 and only if this is false, y > 10 will be evaluated.

Similarly in if(x > 10 && y > 10), x > 10 will be evaluated and only if tihs
is true, y > 10 will be evaluated.

In the case mentioned it won't make a difference, but be careful when doing
something like:

(1) if (++x > 10 || ++y > 10)

as opposed to

(2) if (++x > 10 | ++y > 10)

In (1) ++y will only be execute if ++x is greater than 10, but in (2) both
++x and ++y will be executed.

I don't to confuse the issue, but I do think it's important to keep this in
mind.

or a different example:

if (myObject == null || myObject.TheProperty == 0) ...

*without* short-circuit it would fail on the second test if "myObject"
was null, *with* short-circuit it is perfectly legal.
 
Yes, it is important to keep short-circuiting in mind, but IMHO using a
bitwise operator in a logical operator context is just asking for trouble,
exactly because of side-effects like you get with short circuiting. If
you're performing bit manipulations, use the bitwise operators. If you're
performing conditional tests, use the logical operators.

While it's certainly true that there is an equivalence between a bool value
and a bit, in the sense that you can get by with only one or the other if
you have to, the two exist for a very good reason: they encapsulate
different concepts. Bool exists to represent the abstract concepts "true"
and "false", while bits exist to hold the _numeric_ values 0 and 1. Just
because there is a straightforward mapping from {0,1} to {false,true}
doesn't mean that you should feel free to use the two interchangeably and
still claim that you're writing clean, self-documenting code. You wouldn't
use an int where you want a double, so why would you use a bit where you
want a bool? And along with that philosophy, of course comes the practice
of using the correct operators for the types.
 
I don't know if Marcos is saying that, but I would.

If you are using | and & for conditional tests, and depending upon that
behaviour, then you are writing code that is difficult to read and
maintain. Who is going to notice, in the middle of a 10,000 line
program, that you wrote

if (++x > 10 | ++y > 10)

instead of

if (++x > 10 || ++y > 10)

?

If I saw that sort of code I'd flip out. I would much rather see this:

x += 1; // or x++; if you insist :)
y += 1;
if (x > 10 || y > 10)
....

You need bitwise operators, | and &, in tests only when there are
side-effects, as you pointed out. IMHO it is far, far better style to
remove side effects from conditions wherever possible, because they're
just one more thing to gloss over and miss when reading code.

Just as one vertical bar instead of two, or one ampersand instead of
two is easy to miss when reading code.
 
What kind of convoluted logic is this? For avoiding an or, you are
calling two methods and two properties??

Regards
Senthil
 
What you say makes sense, but then again my example wasn't exactly the best.
I definitely agree that with increments it's better to do them outside the
if, I only used that as an easy example.

All I'm saying is that I find it difficult to believe that there is never a
case where you'd rather use the non-short-circuited version.

Why would the language include the functionality if it's completely useless
(not trying to open another can of worms with this question...)?
 
I wouldn't say that the operators are useless. In fact, they're very
useful for doing bit manipulation. It's probably just an accident of
the language that they can also be used for constructing conditional
expressions that don't short-circuit.

The | and & operators are enormously useful for manipulating Enum types
that have the [Flags] attribute. I use them often for that purpose.

I wouldn't use them in a condition, though, because I could always code
the condition in a different way that wouldn't require it, and the
"different way," although it would be much more long-winded, would be
easier to understand.

In fact, I just thought of an example from my own code. In my WinForms
code I have a method that calls a method for each different control on
my form to validate the control's contents and display an error icon if
it's invalid. I want to call every single method, so that any controls
with bad contents will display an error handler icon next to them. So,
I could say:

return ValidateControl1() & ValidateControl2() & ValidateControl3();

However, how many programmers reading my code would notice that there
was only one &, not two, and so every method would always be called.
Instead, I coded this:

bool control1Valid = ValidateControl1();
bool control2Valid = ValidateControl2();
bool control3Valid = ValidateControl3();
return control1Valid && control2Valid && control3Valid;

Yes, it's four times as much code, but now it's very clear that each
method is called in turn, and then the result is being calculated.
 
Bruce Wood said:
I wouldn't say that the operators are useless. In fact, they're very
useful for doing bit manipulation. It's probably just an accident of
the language that they can also be used for constructing conditional
expressions that don't short-circuit.

I'm not arguing the fact that they are useful as bit-wise operators, that's
a given, you need those.
The | and & operators are enormously useful for manipulating Enum types
that have the [Flags] attribute. I use them often for that purpose.

Same goes for enum manipulation, this is indeed very handy.
I wouldn't use them in a condition, though, because I could always code
the condition in a different way that wouldn't require it, and the
"different way," although it would be much more long-winded, would be
easier to understand.

In fact, I just thought of an example from my own code. In my WinForms
code I have a method that calls a method for each different control on
my form to validate the control's contents and display an error icon if
it's invalid. I want to call every single method, so that any controls
with bad contents will display an error handler icon next to them. So,
I could say:

return ValidateControl1() & ValidateControl2() & ValidateControl3();

However, how many programmers reading my code would notice that there
was only one &, not two, and so every method would always be called.
Instead, I coded this:

This I have a problem with. A programmer who doesn't notice this is
definately not worth his/her salt as a programmer. If you're that concerned
about the quality of the programmers reading your code, why not add a huge
comment block pointing out the fact that you use single &s and not double
&s, this won't waste processor/memory resources of the extra steps and
variables you declare.

I remember a recent discussion about the use of "!" in conditionals, e.g. is
writing if(someBool == false) better coding that if(!someBool)... The
majority of contributors seemed to think the latter, though more difficult
to read, is the better way of coding.
 
It's not a question of "difficulty of reading" code. That's far too
subjective for me. It's a matter of common practice.

If 99% of the conditions out there use && and || (they do), and you're
reading a long program that somewhere in the middle of it there is a
condition that uses & and |, I can almost guarantee that your brain
will "edit in" the usual operators, and you won't even see it. Even if
you pour over the code four or five times, looking for a bug, you won't
see the slight difference from the usual because your brain will gloss
over it, and you'll be _sure_ that you say && and ||, even though
they're not there.

I say this with confidence because I spent 15 years programming in C, a
language in which people do, in fact, do things like that, and I can
tell you that I and a lot of other programmers missed little details
like this. Not because we weren't good programmers (OK, you can debate
that point :) but because we read a lot of code, and our brains started
getting used to how things were "supposed to look" and thus started to
trick us.

If everyone out there used & and | instead of && and || then I would be
coding

if (myObj != null)
{
if (myObj.Prop == 0)
{
... do something ...
}
}

instead of

if (myObj != null && myObj.Prop == 0)
{
... do something ...
}

because the latter would be unexpected.

All I'm saying is that your average programmer is not going to be
expecting & and | in a condition, and so will not readily pick up on
the special behaviour of that condition. It's better to code the whole
thing out in open code where it will be clearly understood.

As for the "extra processor resources" involved... they're not worth
worrying about. Even if by some chance the compiler doesn't compress it
down into the exact same IL as would be produced by using & or |, a few
extra moves in the world of today's computers is trivial.
 
sadhu said:
What kind of convoluted logic is this? For avoiding an or, you are
calling two methods and two properties??

Regards
Senthil
I agree, this would be most puzzling to the average debugger and is
(IMHO) most inefficient and counter intuitive.

JB
At least in my culture.
 
sadhu said:
What kind of convoluted logic is this? For avoiding an or, you are
calling two methods and two properties??

Regards
Senthil

Which takes more /work/

evaluating a method and a property on an existing object

or

comparing two objects with a logical action ?



--
Texeme Textcasting Technology
http://texeme.com

Indie Pop Rocks @ SomaFM
http://somafm.com/
 
Operators are native IL instructions, so they'll be implemented as
efficiently as possible. Your solution involves a call to ToString(),
which happens to be a virtual method, so add in that overhead. You then
call Length, which is a O(n) operation on the length of the string. You
then do the whole thing again, then use the + operator also.
Granted, for tiny strings, it is not much of a deal, but why go through
this much trouble when there is a far *clearer* and effecient solution?

Regards
Senthil
 
Not that it matters much in context, but in .NET calling .Length is not
an O(n) operation on the string. I believe that .NET stores strings as
length-and-contents, not a string terminated by a sentinel like C and
C++. The .Length operator simply fetches the length from the front of
the string. It doesn't count characters like strlen() does.
 
Fair enough, I can see where you're coming from. So we agree that & and |
as conditional operators are parts of C# that they could've left out.

I'm just happy for having && and || in C#, because in my VB6 days it used to
drive me insane to have to code the way you showed below!
 
Fair enough, I can see where you're coming from. So we agree that & and |
as conditional operators are parts of C# that they could've left out.

I'm just happy for having && and || in C#, because in my VB6 days it used to
drive me insane to have to code the way you showed below!

Hi,

I am with Bruce on this one. IMO using | or & as conditional operators
instead of || or && is not recommended. Here is another reason.

Boolean false is generally zero, and true is NOT false. So any non-zero
value equates to be true. This is generally accepted by C programmers
and some have been coding using this fact, e.g., where function return
non zero values denote success (e.g. 0 if a record is not found in a
file, or X where X records have been found).

So consider this (for want of a better example)

if(ValidID && FindRecords())
DisplayRecords();

If ValidID is True and records found then records get displayed. If
Valid is false FindRecords() never gets called. OK so far.

Now consider this

if(ValidID & FindRecords())
DisplayRecords();

If ValidID is true (non zero value). This value depends on the compiler
or the programmer. But what is non-zero? Some say -1 and others say 1.
Whatever. Let's say this is 1 for this example.

If FindRecords() returns 2, denoting 2 records found:

1 & 2 (bitwise calculation) is 0, making this expression false. So
DisplayRecords() never gets called which is wrong, of course.

Admittedly this is not a good example but you get the idea of a possible
dangerous side effect.

Cheers,

Paul.
 
Back
Top