About us

My photo
Laziness is the mother of efficiency. We believe we are efficient guys!!

Monday, May 2, 2011

A short note about short-circuiting

A short note about short-circuiting

C# (almost all the languages) has the feature called short-circuiting. This is used when evaluating expressions that use “and” and “or” operators. You might have experienced this feature. If not, let us learn through the below code snippet.

class Program
{
public static void Main(string[] args)
{
if(methodOne() && methodTwo())
{
Console.WriteLine("In Then block");
}
else
{
Console.WriteLine("In Else block");
}

Console.ReadKey(true);
}

private static bool methodOne()
{
Console.WriteLine("In methodOne");
return false;
}

private static bool methodTwo()
{
Console.WriteLine("In methodTwo");
return false;
}
}

If you run the above code snippet, ideally, the output should be,

In methodOne
In methodTwo
In Else block

But the actual result will be

In methodOne
In Else block

Surprised? Just recall the logical AND gate table.

Input AInput BOutput
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse



Here, if you check, even if one of the value is false, (no matter what the other value is), the output will always be false. In our case, the first part (method call “methodOne”) will be evaluated and determined as false. So, even if methodTwo() returns a true, still the expression will result as false. So C# (and most other languages) won’t process the second part of the expression and just enters into the else part to proceed. Hence, we got the above output.

Let us check the functionality of OR operator (||).

public static void Main(string[] args)
{
if(methodOne() || methodTwo())
{
Console.WriteLine("In Then block");
}
else
{
Console.WriteLine("In Else block");
}

Console.ReadKey(true);
}

private static bool methodOne()
{
Console.WriteLine("In methodOne");
return true;
}

private static bool methodTwo()
{
Console.WriteLine("In methodTwo");
return false;
}

This is similar to the above snippet, except that we have changed the return value of methodOne, and the expression in the “if” statement. Now, let us check the output.

The output will be

In methodOne
In Then block

instead of

In methodOne
In methodTwo
In Then block

The reason is same. Since, first part of expression evaluates to true, the second part of the expression will not be checked (this is because, irrespective of the result, always the condition will succeed). Please refer the below table of logical OR gate.


Input AInput BOutput
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse



In our case, the second part is just a simple method call. If the second part is a very big expression, the runtime will unnecessarily spend time in checking the second part, which anyway will not affect the result.

(Please note, if the first part’s result is not enough to determine the result of the expression i.e., if first part returns true in first code snippet, then runtime will always go for evaluating the second part.)

So the runtime, safely skips the second part, saves some time and proceeds with the next valid executable statement. This is called short-circuiting. This is the common behavior of many languages.

From the beginning, I am using, “most of the”, “many of the” prefixes to “languages” so far, as the language, Visual Basic (all flavors including .NET!) will always evaluate both parts of the expression before moving into Then or Else parts. However, they have (from .NET 1.0 I guess) introduced two new operators “AndAlso”, and “OrElse” which provides the short-circuiting behavior to VB.NET programmers. So if you are a VB.NET programmer, be careful before using normal “And” and “Or” operators hereafter :)

Overriding short-circuiting behavior

Even though, we find this short-circuiting behavior is cute and saves some time, we may have some situations where we don’t want this behavior.For example, (our above sophisticated scenario is one good example!!) if you port a VB program into C# and want to maintain the same “And’ and “Or” functionality in C# as well, you may have to override this behavior. I really don’t see any other genuine reasons to avoid this feature (if you know, please share with me through comments).

C# (I am not sure about the other languages), offers a way to override this default behavior. We can rewrite the “if” statement of the second code snippet as given below.

if(methodOne() | methodTwo())

Note that, there is now only one pipe symbol (|) in place. This will force the runtime to evaluate both the parts of the expressions and complete the evaluation. So, the result will be

In methodOne
In methodTwo
In Then block

The same can be done for && operator. Just replace && with single & and check the first code snippet the answer will be

In methodOne
In methodTwo
In Else block

So, what this single pipe symbol or single ampersand symbol really does? These operators are called bitwise operators. These will evaluate the expressions fully, obtain both the results, check them bit wise and derive the answer. Based on the answer, they will act upon.

Check the output of below two statements.


Console.WriteLine(4 | 6);
Console.WriteLine(4 & 6);

The output will be 6 and 4 respectively. They will operate on bitwise on both 4, 6 like below.

4 = 100 (binary equivalent)
6 = 110 (binary equivalent)

Now let’s do a bitwise OR.

4 | 6 will be converted to
100
|||
110
===
110
===

ie from right to left, 0 or 0, 0 or 1, 1 or 1. Then the result is converted into decimal and the answer is 6. The same applies for bitwise AND.

4 & 6 will be converted to

100
&&&
110
===
100
===

ie, from right to left, 0 and 0, 0 and 1, 1 and 1. Then the answer is converted to decimal and the answer is 4!

Since, both the results are required, to perform the bitwise OR and AND, the short-circuiting functionality is overridden. The same is happening for bool in the above code snippet. The operators evaluate both expressions and do a bitwise operation on them and produces the result. This is a suggested way by Microsoft to override the short-circuiting behavior.

Happy coding!

No comments:

Post a Comment