Search code examples
c#optimizationcoding-style

Is there any advantage in writing a set of operations in a single line if all those operations have to occur anyway?


From a post-compilation perspective (rather than a coding syntax perspective), in C#, is there any actual difference in the compiled code between a set of operations that have occurred on one line to a set of operations that occur across multiple lines?

This

object anObject = new object();
anObject = this.FindName("rec"+keyPlayed.ToString());
Rectangle aRectangle = new Rectangle();
aRectangle = (Rectangle)anObject;

vs this.

Rectangle aRectangle = (Rectangle)this.FindName("rec"+keyPlayed.ToString());

I wonder because there seems to be a view that the least amount of lines used is better however I would like to understand if this is because there is a tangible technical benefit or if there was at some point a tangible benefit or if it is indeed for a reason that is quantifiable?


Solution

  • The number of lines don't matter; the IL will be identical if the code is equivalent (your's isn't).

    And actually, unless we know what FindName returns, we can't answer properly - since by casting to object you might be introducing a "box" operation, and you might be changing a conversion operation (or perhaps a passive no-op cast) into an active double-cast (cast to object, cast to Rectangle). For now, I'll assume that FindName returns object, for simplicity. If you'd used var, we'd know at a glance that your code wasn't changing the type (box / cast / etc):

    var anObject = this.FindName("rec"+keyPlayed.ToString());
    

    In release mode (with optimize enabled) the compiler will remove most variables that are set and then used immediately. The biggest difference between the two lines above is that the second version doesn't create and discard new object() and new Rectangle(). But if you hadn't have done that, the code would have been equivalent (again, assuming that FindName returns object):

    object anObject;
    anObject = this.FindName("rec"+keyPlayed.ToString());
    Rectangle aRectangle;
    aRectangle = (Rectangle)anObject;
    

    Some subtleties exist if you re-use the variable (in which case it can't necessarily be removed by the compiler), and if that variable is "captured" by a lambda/anon-method, or used in a ref/out. And some more subtleties for some math scenarios if the compiler/JIT chooses to do an operation purely in the registers without copying it back down to a variable (the registers have different (greater) width, even for "fixed-size" math like float).