Pergunta

If I have this code:

if (isFoo() && isBar())
{
    ...
}

The program will calculate the first condition, then calculate the second condition, then determine whether to go through or skip the block below.

However, if I nest the conditions like so:

if (isFoo())
    if(isBar())
    {
        ...
    }

Now it checks the first condition, and if it's false it doesn't bother with the second condition.

If the second condition (being a function) is a time-consuming memory-expensive hog it seems to be better to nest it.

Is this true? I've never seen code like this before and I made an assumption after the first example, but IMO it's highly possible.

Foi útil?

Solução 2

In C#/C++ and many other languages you have two logical AND operators actually: & and &&:

& operator will evaluate both conditions

&& operator will evaluate only first, and if it equals FALSE, than it skips second part of expression.

The same applies for logical OR operators too. There are two operator: | and ||:

| operator will evaluate both conditions

|| operator will evaluate only first, and if it equals TRUE, than it skips second part of expression.

So, answering your question, in your example you are using &&, which will behave as two nested if's

[EDIT]: Ok, it is not that easy to find example of using of | and &, personally I have used them in shortest-code contests)) This is where they are really useful (not because they are shorter than && and ||). Also consider following example:

static bool LaunchFirstRocket()
{
    // Launching rocket if all is ok return true, or return false if we failed to launch it.
}

static bool LaunchSecondRocket()
{
    // Launching rocket if all is ok return true, or return false if we failed to launch it.
} 

static void Main(string[] args)
{
    if (LaunchFirstRocket() & LaunchSecondRocket())
    {
        Console.WriteLine("Both rockets have launched successfully!");
    }
}

Here we will force to execute both methods regardless of outcome of first one. If first rocket failed, we still want to launch second one, this is our logic. Yes, there are a LOT of other ways to write such code, but this is just an example for educational purposes.

Outras dicas

It depends from programming language.

Most of modern/popular languages support Short circuit evaluation which means that program doesn't evaluate the whole expression, but stops evaluation immediately after gets the result of the whole expression (others gave examples already).

But there are exceptions

Two languages I know which doesn't support short circuit evaluation are Microsoft VB(6) and VB.NET.

VB6 doesn't support it at all, so here nesting Ifs if common optimization technique. Moreover in expressions like

If Not rs Is Nothing And Not rs.EOF

not using nesting Ifs gives execution error while rs is Nothing.

VB.NET introduced two new logical operators AndAlso and OrElse which support short circuit evaluation.

Standard VB.NET And and Or operators doesn't support short circuit evaluation, which is common source of bugs in case of newcomer developers.

Optimalizations

In both cases (language supports and not short circuit evaluation) you can check expressions in order of quicker to evaluate first.

So instead of (checking in DB if user is female, with even key and it's logged in):

if (db.getUserSex() == FEMALE && userKey % 2 == 0 && userKey % 2 && isUserLogged)

use (check if logged in (boolean), with even key (arithmetic operator) and check gender in DB in the end):

if (isUserLogged && userKey % 2 == 0 && db.getUserSex() == FEMALE)

I believe most compiler would do this optimization for you. If the first condition of && is false, the second one would not be executed.

The program will calculate the first condition, then calculate the second condition,

No, not in most modern languages (for example C, C++). Since it's known that if the first condition is false, then the value of the AND expression cannot possibly be anything other than false, so the second part is not evaluated. In these two languages, the standard explicitly defines this optimization (called "short-circuit evaluation").

It depends. As others have noted, in compiled languages with short-circuit evaluation (such as C and C++), both versions will likely compile to exactly the same code.

In some interpreted languages, such as Perl, the second version may, in fact, be very slightly slower than the first, because there is a tiny amount of overhead in entering a code block. For instance, this artificial benchmark shows the difference clearly:

use Benchmark ':all';
my $count = shift || 10_000_000;
our ($foo, $bar, $baz) = (1, 1, 1);
timethese( $count, {
    'and'    => 'if ($foo && $bar) { $baz++; }',
    'nested' => 'if ($foo) { if ($bar) { $baz++; } }',
});

Output:

Benchmark: timing 10000000 iterations of and, nested...
       and:  2 wallclock secs ( 2.41 usr +  0.00 sys =  2.41 CPU) @ 4149377.59/s (n=10000000)
    nested:  4 wallclock secs ( 3.54 usr +  0.00 sys =  3.54 CPU) @ 2824858.76/s (n=10000000)

In practice, of course, the difference is likely to be completely insignificant, especially compared to the general overhead of using an interpreted language to begin with.

All modern languages will short-circuit any AND'ed clauses. So, in your example, if isFoo() was false, it wouldn't even bother checking isBar(), and it would exit the if statement.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top