C# supplies special short-circuit versions of its AND and OR logical operators that can be used to produce more efficient code. To understand why, consider the following: In an AND operation, if the first operand is false, the outcome is false no matter what value the second operand has. In an OR operation, if the first operand is true, the outcome of the operation is true no matter what the value of the second operand. Thus, in these two cases there is no need to evaluate the second operand. By not evaluating the second operand, time is saved and more efficient code is produced.
The short-circuit AND operator is && and the short-circuit OR operator is | |. As described earlier, their normal counterparts are & and |. The only difference between the normal and short-circuit versions is that the normal operands will always evaluate each operand, but short-circuit versions will evaluate the second operand only when necessary.
Here is a program that demonstrates the short-circuit AND operator. The program determines if the value in d is a factor of n. It does this by performing a modulus operation. If the remainder of n / d is zero, then d is a factor. However, since the modulus operation involves a division, the short-circuit form of the AND is used to prevent a divide-by-zero error.
// Demonstrate the short-circuit operators, using System; class SCops { public static void Main() { int n, d; n = 10; d = 2; if(d != 0 && (n % d) == 0) Console.WriteLine(d + " is a factor of " + n); d = 0; // now, set d to zero // Since d is zero, the second operand is not evaluated, if(d != 0 && (n % d) == 0) Console.WriteLine(d + " is a factor of " + n); /* Now, try the same thing without short-circuit operator. This will cause a divide-by-zero error. */ if(d != 0 & (n % d) == 0) Console.WriteLine(d + " is a factor of " + n); } }
To prevent a divide-by-zero error, the if statement first checks to see if d is equal to zero. If it is, the short-circuit AND stops at that point and does not perform the modulus division. Thus, in the first test, d is 2 and the modulus operation is performed. The second test fails because d is set to zero, and the modulus operation is skipped, avoiding a divide-by-zero error. Finally, the normal AND operator is tried. This causes both operands to be evaluated, which leads to a runtime error when the division-by-zero occurs.
Since the short-circuit operators are, in some cases, more efficient than their normal counterparts, you might be wondering why C# still offers the normal AND and OR operators. The answer is that in some cases you will want both operands of an AND or OR operation to be evaluated because of the side effects produced. Consider the following:
// Side effects can be important, using System; class SideEffects { public static void Main() { int i; bool someCondition = false; i = 0; /* Here, i is still incremented even though the if statement fails. */ if(someCondition & (++i < 100)) Console.WriteLine("this won't be displayed"); Console.WriteLine("if statement executed: " + i); // displays 1 /* In this case, i is not incremented because the short-circuit operator skips the increment. */ if(someCondition && (++i < 100)) Console.WriteLine("this won't be displayed"); Console.WriteLine("if statement executed: " + i); // still 1 !! } }
First, notice that the bool variable someCondition is initialized to false. Next, examine each if statement. As the comments indicate, in the first if statement, i is incremented despite the fact that someCondition is false. When the & is used, as it is in the first if, the expression on the right side of the & is evaluated no matter what value the expression on the left has. However, in the second if statement, the short-circuit operator is used. In this case, the variable i is not incremented because the left operand, someCondition, is false, which causes the expression on the right to be skipped. The lesson here is that if your code expects the right-hand operand of an AND or OR operation to be evaluated, then you must use C#'s non-short-circuit forms of these operations.
No comments:
Post a Comment