C#: Compiler optimization, function calls, and Boolean expression short-circuiting - c#

Let's assume that we have the following expensive functions:
bool ExpensiveOp1() { ... }
bool ExpensiveOp2() { ... }
bool ExpensiveOp3() { ... }
Also, to keep it simple, assume that none of them have side effects.
I know that C# can short-circuit if ExpensiveOp1 or ExpensiveOp2 returns false in the following expression:
return ExpensiveOp1() && ExpensiveOp2() && ExpensiveOp3();
However, is the compiler smart enough to (for lack of a better term) inline the function calls and take advantage of short-circuiting if I write the code this way?
var x = ExpensiveOp1();
var y = ExpensiveOp2();
var z = ExpensiveOp3();
return x && y && z;

No, and for a good reason. The compiler doesn't know if any of your operations have side effects, so if you run them outside of a boolean short circuiting situation it runs them in case there are side effects you want.

Related

Using &= on boolean values in C#

I have a method in C# called SendEvent that returns a bool which represents if it was successful or not. I want to loop through a number of objects and call SendEvent on them all, and in the end, have a result variable that is a bool, that is true if all SendEvent calls succeeded, and false if at least one failed.
At first I did this:
bool result = true;
for (int i = 0; i < myObjects.Length; i++)
{
result = result && myObjects[i].SendEvent();
}
But that will cause that the SendEvent will not be called on subsequent objects if one fails, as the right hand side of the && operator won't be executed if result is false.
So I turned it around, to:
bool result = true;
for (int i = 0; i < myObjects.Length; i++)
{
result = myObjects[i].SendEvent() && result;
}
But I found that somewhat ugly. Can I use the bitwise &= operator to always execute the SendEvent call, and set the value of result, like this?
bool result = true;
for (int i = 0; i < myObjects.Length; i++)
{
result &= myObjects[i].SendEvent();
}
How does the &= work on boolean values? Will it execute both sides of the operator? What will end up in the result variable?
As you can read here, both & and && are defined for bools as "logical and", but && will short-circuit: in case the first operand is false the expression on the right will not be evaluated. Regardless what the outcome of the expression on the right is, the result of the && expression will remain false. This is usually a "performance hack" in the first place, but if the right expression has side-effects, could throw an exception, etc., it is something you have to take into account. The same happens for the || operator if the first operand is true.
So if you want to evaluate both sides first, you can indeed use:
result = result & myObjects[i].SendEvent();
or shorter:
result &= myObjects[i].SendEvent();
Background
As is written in the language specifications:
The operation
x && y
corresponds to the operation
x & y
except that if x is false, y is not evaluated, because the
result of the AND operation is false no matter what the value of y
is. This is known as "short-circuit" evaluation.
Note that there is no &&= operator (at least at the time I am writing this). This looks reasonable since usually with an ..= operator, you would expect that the operand is first evaluated and then some operation is done on the variable to the left. Of course it is all a matter of style and taste, but I would reason that a hypothetical &&= does not give "enough hints" that the right operand will not be called in all cases.
As a LINQ lover, I would do it like:
var result = (myObjects.Count(obj => obj.SendEvent()) == myObjects.Length);
In case you want to break the loop on the first false value, it coud be:
var result = myObjects.All(obj => obj.SendEvent());

Does comparing to Math.Min or Math.Max short-circuit?

When comparing to a minimum or maximum of two numbers/functions, does C# short-circuit if the case is true for the first one and would imply truth for the second? Specific examples of these cases are
if(x < Math.Max(y, z()))
and
if(x > Math.Min(y, z()))
Since Math.Max(y, z()) will return a value at least as large as y, if x < y then there is no need to evaluate z(), which could take a while. Similar situation with Math.Min.
I realize that these could both be rewritten along the lines of
if(x < y || x < z())
in order to short-circuit, but I think it's more clear what the comparison is without rewriting. Does this short-circuit?
As others have pointed out, the compiler knows nothing about the semantics of Min or Max that would allow it to break the rule that arguments are evaluated before the method is called.
If you wanted to write your own, you could do so easily enough:
static bool LazyLessThan(int x, int y, Func<int> z)
{
return x < y || x < z();
}
and then call it
if (LazyLessThan(x, y, z))
or
if (LazyLessThan(x, y, ()=>z()))
Or for that matter:
static bool LazyRelation<T>(T x, T y, Func<T> z, Func<T, T, bool> relation)
{
return relation(x, y) || relation(x, z());
}
...
if (LazyRelation(x, y, ()=>z, (a,b)=> a < b)))
No, it doesn't short circuit and z() will always be evaluated. If you want the short circuiting behavior you should rewrite as you have done.
Math.Min() and Math.Max() are methods just like any other. They have to be evaluated in order to return the value which will be used as the second argument in the comparison. If you want short-circuiting then you will have to write the condition using the || operator as you have demonstrated.
(Nothing particularly new to add, but I figured I'd share the results of a test I ran on it.)
Math.Max() could easily be inlined by the CLR's just-in-time compiler and from there I was curious whether it might further optimize the code in such a way that it is short-circuited.
So I whipped up a microbenchmark that evaluates the two expressions 1,000,000 times each.
For z(), I used a function that calculates Fib(15) using the recursive method. Here are the results of running the two:
x < Math.Max(y, z()) : 8097 ms
x < y || x < z() : 29 ms
I'm guessing the CLR won't transform the code in any way that prevents method calls from executing, because it doesn't know (and doesn't check to see if) the routine has any side effects.
No, it doesnt short circuit, at least at the C# compiler level. Math.Min or Math.Max are two ordinary static method calls and the compiler will not optimize in that sense.
The order of evaluation of the code will be: z(), Math.Max, x > ...
If you really want to make sure, check out the IL code.

Problem with operator &&

Considering the following code
public bool GetFalse()
{
return false;
}
public bool GetTrue()
{
return true;
}
How can I force this expression GetFalse() && GetTrue() to execute second Method?
Try with:
GetFalse() & GetTrue()
You can't because the logical AND operator short circuits. In the general case it is a good idea to avoid side effects from expressions like that, although there are perfectly valid uses (i.e., if( someObj != null && someObj.Value == whatever ). You could use the bitwise and operator (&) which does not short circuit, but again, I wouldn't do that.
You should split those two method calls into variables first and then perform the check if you need them both to execute.
bool first = SomeMethodCall();
bool second = SomeMethodThatMustExecute();
if( first && second )
{
// ...
}
Use the non-short circuiting version (also known as the bit-wise AND when not working with Boolean values):
GetFalse() & GetTrue();
This is an optimization issue. Since the first method called in the expression is false, the entire expression cannot be true, so the second method in the expression is not called. If it is necessary to call this for a side effect (bad practice to rely on a side effect, but YMMV), something like this should be used:
x = GetFalse();
y = GetTrue();
if (x && y) ...
Assuming that your actual functions perform some specific tasks and return a value indicating (for example) success or failure I would prefer to see this written as
bool fooResult = DoFoo();
bool barResult = DoFar();
And then you can use fooResult && barResult in your code.

How-to: short-circuiting inverted ternary operator implemented in, e.g. C#? Does it matter?

Suppose you are using the ternary operator, or the null coalescing operator, or nested if-else statements to choose assignment to an object. Now suppose that within the conditional statement, you have the evaluation of an expensive or volatile operation, requiring that you put the result into a temporary variable, capturing its state, so that it can be compared, and then potentially assigned.
How would a language, such as C#, for consideration, implement a new logic operator to handle this case? Should it? Are there existing ways to handle this case in C#? Other languages?
Some cases of reducing the verbosity of a ternary or null coalescing operator have been overcome, when we assume that we are looking for direct comparisons, for example. See Unique ways to use the Null Coalescing operator, in particular the discussion around how one can extend the usage of the operator to support String.IsNullOrEmpty(string). Note how Jon Skeet is using the PartialComparer from MiscUtil, to reformat 0s to nulls,
Why is this possibly necessary? Well, take a look at how we write a comparison method for complex objects without any shortcuts (examples from the cited discussions):
public static int Compare( Person p1, Person p2 )
{
return ( (result = Compare( p1.Age, p2.Age )) != 0 ) ? result
: ( (result = Compare( p1.Name, p2.Name )) != 0 ) ? result
: Compare( p1.Salary, p2.Salary );
}
Jon Skeet writes a new comparison to fallback the equality case. This allows the expression to extend by writing a new specific method which returns null, allowing us to use the null coalescing operator:
return PartialComparer.Compare(p1.Age, p2.Age)
?? PartialComparer.Compare(p1.Name, p2.Name)
?? PartialComparer.Compare(p1.Salary, p2.Salary)
?? 0;
The null coalescing operator is more readable because it has two sides, not three. The boolean condition clause is separated into a method, in this case returning null if the expression must be continued.
What would the above expression look like if we could more easily put the condition in-line? Take the expression from PartialComparer.Compare which returns null, and place it in a new ternary expression which allows us to use the evaluation of the left-side expression, with an implicit temporary variable value:
return Compare( p1.Age, p2.Age ) unless value == 0
: Compare( p1.Name, p2.Name ) unless value == 0
: Compare( p1.Salary, p2.Salary );
The basic "flow" of an expression would be:
expression A unless boolean B in which case expression C
Rather than being an overloaded comparison operator, I suppose this is more like a short-circuiting inverted ternary operator.
Would this type of logic be useful? Currently the null coalescing provides us a way to do this with the conditional expression (value == null).
What other expressions would you want to test against? We've heard of (String.IsNullOrEmpty(value)).
What would be the best way to express this in the language, in terms of operators, keywords?
personally I'd avoid the short circuit from operators and just let the methods chain it:
public static int CompareChain<T>(this int previous, T a, T b)
{
if (previous != 0)
return previous;
return Comparer<T>.Default.Compare(a,b);
}
use like so:
int a = 0, b = 2;
string x = "foo", y = "bar";
return a.Compare(b).CompareChain(x,y);
can be inlined by the JIT so it can perform just as well as short circuiting built into the language without messing about with more complexity.
In response to your asking whether the above 'structure' can apply to more than just comparisons then yes it can, by making the choice of whether to continue or not explict and controllable by the user. This is inherently more complex but, the operation is more flexible so this is unavoidable.
public static T ElseIf<T>(
this T previous,
Func<T,bool> isOK
Func<T> candidate)
{
if (previous != null && isOK(previous))
return previous;
return candidate();
}
then use like so
Connection bestConnection = server1.GetConnection()
.ElseIf(IsOk, server2.GetConnection)
.ElseIf(IsOk, server3.GetConnection)
.ElseIf(IsOk, () => null);
This is maximum flexibility in that you can alter the IsOk check at any stage and are entirely lazy. For situations where the is OK check is the same in every case you can simplify like so and entirely avoid extensions methods.
public static T ElseIf<T>(
Func<T,bool> isOK
IEnumerable<Func<T>[] candidates)
{
foreach (var candidate in candidates)
{
var t = candidate();
if (isOK(t))
return t;
}
throw new ArgumentException("none were acceptable");
}
You could do this with linq but this way gives a nice error message and allows this
public static T ElseIf<T>(
Func<T,bool> isOK
params Func<T>[] candidates)
{
return ElseIf<T>(isOK, (IEnumerable<Func<T>>)candidates);
}
style which leads to nice readable code like so:
var bestConnection = ElseIf(IsOk,
server1.GetConnection,
server2.GetConnection,
server3.GetConnection);
If you want to allow a default value then:
public static T ElseIfOrDefault<T>(
Func<T,bool> isOK
IEnumerable<Func<T>>[] candidates)
{
foreach (var candidate in candidates)
{
var t = candidate();
if (isOK(t))
return t;
}
return default(T);
}
Obviously all the above can very easily be written using lambdas so your specific example would be:
var bestConnection = ElseIfOrDefault(
c => c != null && !(c.IsBusy || c.IsFull),
server1.GetConnection,
server2.GetConnection,
server3.GetConnection);
You've got lots of good answers to this question already, and I am late to this particular party. However I think it is worthwhile to note that your proposal is a special case of a more generally useful operation which I dearly wish C# had, namely, the ability to in an expression context, give a name to a temporary computation.
In fact C# has this operator but only in query comprehensions. I wish we had been able to add this as an operator in C# 3:
public static int Compare(Person p1, Person p2) =>
let ages = Compare(p1.Age, p2.Age) in
ages != 0 ?
ages :
let names = Compare(p1.Name, p2.Name) in
names != 0 ?
names :
Compare(p1.Salary, p2.Salary);
"Let expressions" are one of those expressions that are so useful, and found in so few languages, and I genuinely do not understand why language designers do not add it immediately in version one.
If C# had this feature then your proposed:
A() unless B() : C()
is simply
let a = A() in B() ? C() : a
which is hardly more difficult to understand, and bonus, you get to use a in expressions B() and C() if you like.
Let expressions can be emulated in any language that has lambdas; of course let x = y in z is simply (x=>z)(y), but there is no concise way to write that in C# either because C# requires a conversion to a delegate type on every lambda.
Incidentally, in Roslyn we do not represent temporaries as let-expressions, though we could. Rather, we go even one level below that and have a representation for "sequence of operations that might produce values, one of which will become the value of this expression". "let x = y in z" is simply the sequence "allocate x, x = y, z, deallocate x" where the third element is the value. And in the original pre-roslyn C# compiler we had internal operators "left" and "right", which were binary operators that took two expressions and produced either the left or right side, so we could generate ((allocate x) right ((x = y) right z)) left (deallocate x).
My point here is: we often get requests for bespoke language features with unusual punctuation, but it would in general have been better to implement the basic building blocks that you could build these operators out of in a natural way.
To place one proposed implementation away from a very verbose question, let's run with the unless keyword.
(expression A) unless (boolean B) <magical "in which case" operator> (expression C)
... would be all there is to it.
Boolean expression B would have access to the evaluation of expression A through the keyword value. Expression C could have the unless keyword in its expression, allowing for simple, linear chaining.
Candidates for the <magical "in which case" operator>:
:
|
?:
otherwise keyword
Usage of any symbols tend to diminish readability for the average developer. Even the ?? operator is not used widely. I, myself, do prefer to develop verbose code, but that I can easily read one year from now.
So a candidate for your :
expression A unless boolean B in which case expression C.
would be
expression A unless boolean B sothen expression C.
Although many people like me would still use:
if (B) {expression C;}
else {expression A;}
This comes in when you are developing a software with a big team, with different backgrounds, each one on the team master of one language, and just user of others.
More #ShuggyCoUk: Ah, I see that this might work for more than just comparisons? I haven't used C# 3 and extension methods, but I suppose you can declare, for my previous example, below, a
public delegate bool Validation<T>( T toTest );
public static T Validate<T>( this T leftside, Validation<T> validator )
{
return validator(leftside) ? leftside : null;
}
Followed by, per Skeet:
Validation<Connection> v = ( Connection c ) => ( c != null && !( c.IsBusy || c. IsFull ) );
Connection bestConnection =
server1.GetConnection().Validate( v ) ??
server2.GetConnection().Validate( v ) ??
server3.GetConnection().Validate( v ) ?? null;
Is this how that would work in C#? Comments appreciated. Thank you.
In response to ShuggyCoUk:
So this is an extension method in C# 3, then? Also, the result here is an int, not an arbitrary expression. Useful for overloading yet another comparison method. Suppose I wanted an expression for choosing the best connection. Ideally, I want something to simplify the following:
Connection temp;
Connection bestConnection =
( temp = server1.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull) ? temp
: ( temp = server2.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull ) ? temp
: ( temp = server3.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull ) ? temp
: null;
Ok, so one could have a method
bool IsOk( Connection c )
{
return ( c != null && !(c.IsBusy || c.IsFull) );
}
Which would produce:
Connection temp;
Connection bestConnection =
( temp = server1.GetConnection() ) && IsOk( temp ) ? temp
: ( temp = server2.GetConnection() ) && IsOk( temp ) ? temp
: ( temp = server3.GetConnection() ) && IsOk( temp ) ? temp
: null;
But how would method chaining for comparisons work, here? I am pondering something which looks like:
Connection bestConnection =
server1.GetConnection() unless !IsOk(value) otherwise
server2.GetConnection() unless !IsOk(value) otherwise
server3.GetConnection() unless !IsOk(value) otherwise null;
I think that there are so far, hoops to jump through, if I want the result of a conditional to be an expression or result of a method which was in the original conditional.
I assume that the object returned by such methods will be expensive to produce, or will change the next time the method is called.

Speed of boolean expression (C#)

Hello I was thinking of what is better to write (in matter of speed and/or efficiency):
bool Method(...) { ... }
...
bool result = Method(...);
if (result == false)
{ ... }
// or
if (!result)
{ ... }
Or, alternatively...
if (result == true)
// or
if (result)
I'm asking because I use first one (result == false) but sometimes it gets very long, especially in condition ? expr : expr statements.
Personally, I cringe whenever I see something like result == false. It's a rather nasty misuse of the equality operator in my opinion, and totally unnecessary. While I'd imagine the compiler should turn the two expressions into the same byte code, you definitely want to be using !result. Indeed, it is not only the more direct and logical expression, but as you mention, makes the code a good deal shorter and more readable. I think the vast majority of C# coders would agree with me on this point.
Runtime speed is the same - both snippets compile to the same MSIL code representation.
Using (result == false) instead of (!result) feels kinda sloppy though.
There is no performance difference in runtime code. Most of the coding-guidelines in the companies i worked prefer !result.
I don't think there is any difference, and if there is you would probably have a hard time measuring it. Any difference is likely to be in the noise of the measurement.
You should definitely use the expression with the ! operator, not because it's faster but because it's safer.
If you accidentally use one equals sign instead of two, you assign the value to the variable instead of comparing the values:
if (result = false) {
For other data types the compiler can catch this, as an expression like (id = 42) has an integer value so it can't be used in the if statement, but an expression like (result = false) has a boolean value so the compiler has to accept it.
(An old C trick is to put the literal first so that it can't be an assignment, but that is less readable so the ! operator is a better alternative.)
I think there are three steps in this process. First, you believe that there should always be a comparison inside an if, so you write if(this.isMonkey == true) banana.eat();
Or, more realistically
if(SpeciesSupervisor.getInstance().findsSimilarTo(Monkey.class, 2) == true) {
String f = new PropertyBundle("bananarepo").getField("banana store");
EntitiyManager.find(Banana.class,f).getBananas().get(1).eat();
}
Then, you learn that it is fine to ask if(this.isMonkey) and that this formatting allows better reading as a sentence in this example ("if this is a monkey").
But at last, you get old and you learn that if(b) is not very readable, and that if(b==true) gives your poor brain some clue what is happening here, and that all these harsh claims of "misuse", "abuse", yada yada, are all a little overstated.
And as for the performance. In Java it would not make a shred of difference. I don't think .NET is so much worse. This is the easiest optimization a compiler could do, I would bet some money that the performance is the same.
Cheers,
Niko
Although I agree with #Noldorin that if(!result) is to be preferred, I find that if(result == false) and its ilk are very useful if you have to test a nullable bool, which most frequently happens in data access scenarios.
Edit: Here's a sample program that explains the different ways you can use the equality operator on a nullable bool.
class Program
{
static void Main(string[] args)
{
TestNullBool(true);
TestNullBool(false);
TestNullBool(null);
Console.ReadKey();
}
private static void TestNullBool(bool? result)
{
if (result == null)
{
Console.WriteLine("Result is null");
}
if (result == false)
{
Console.WriteLine("Result is false");
}
if (result == true)
{
Console.WriteLine("Result is true");
}
}
}
/* Output:
Result is true
Result is false
Result is null
*/

Categories

Resources