Differences between If and ternary operator ?:

Asked

Viewed 13,820 times

46

There is a difference in performance between using an if and a ternary operator in C#?

Utilise Resharper (Productivity tool for VS), he insists that the ternary operator is better but doesn’t explain to me why.

Code, before the Refactoring:

if (int.Parse(dr.ItemArray[16].ToString()) == 1)
{
   txt.Append(@"VENDE-SE");
}
else
{
  txt.Append(@"ALUGA-SE");
}

Afterward:

txt.Append(int.Parse(dr.ItemArray[16].ToString()) == 1
        ? @"VENDE-SE"
        : @"ALUGA-SE");
  • 5

    The difference is in readability... not that one is more than the other, but that, in certain situations, one is more readable than the other.

  • 2

    As I know Resharper analyzes the "simplicity" of the if and suggests the expression "?:" to replace the if. I believe you’ve won in performance, yes, but nothing that significant. But consider one thing, analyze the full reading of your code and see if it is readable to other programmers. The excessive use of this expression can cause confusion in the reading of the code, hindering a future reading for maintenance in the application.

  • 1

    agree, not always the ?: helps readability, in the example above I think begins the limit that does not compensate for the use of it. usually use for something simple like Return (id == null ? 0 : id);

  • In that case, to decrease code could just remove the keys

  • @Dorathoto you should have left the reward 1 week to highlight your question.

  • But your answer is already 100% good...

Show 1 more comment

2 answers

47


The code

public class Exemplo {
    public static void Main(string[] args) {
        var x = 0;
        if (x == 1) {
            x = 1;
        } else {
            x = 2;
        }
    }
}

is compiled to

.method public hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 22 (0x16)
    .maxstack 2
    .locals init (
        [0] int32,
        [1] bool
    )

    IL_0000: nop                  // Do nothing (No operation)
    IL_0001: ldc.i4.0             // Push 0 onto the stack as int32
    IL_0002: stloc.0              // Pop a value from stack into local variable 0
    IL_0003: ldloc.0              // Load local variable 0 onto stack
    IL_0004: ldc.i4.1             // Push 1 onto the stack as int32
    IL_0005: ceq                  // Push 1 (of type int32) if value1 equals value2, else push 0
    IL_0007: stloc.1              // Pop a value from stack into local variable 1
    IL_0008: ldloc.1              // Load local variable 1 onto stack
    IL_0009: brfalse.s IL_0011    // Branch to target if value is zero (false), short form
    IL_000b: nop                  // Do nothing (No operation)
    IL_000c: ldc.i4.1             // Push 1 onto the stack as int32
    IL_000d: stloc.0              // Pop a value from stack into local variable 0
    IL_000e: nop                  // Do nothing (No operation)
    IL_000f: br.s IL_0015         // Branch to target, short form
    IL_0011: nop                  // Do nothing (No operation)
    IL_0012: ldc.i4.2             // Push 2 onto the stack as int32
    IL_0013: stloc.0              // Pop a value from stack into local variable 0
    IL_0014: nop                  // Do nothing (No operation)
    IL_0015: ret                  // Return from method, possibly with a value
} // end of method Exemplo::Main

Can be observed in the Sharplab.

And the code

public class Exemplo {
    public static void Main(string[] args) {
        var x = 0;
        x = (x == 1 ? 1 : 2);
    }
}

is compiled to

.method public hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 13 (0xd)
    .maxstack 2
    .locals init (
        [0] int32
    )

    IL_0000: nop                  // Do nothing (No operation)
    IL_0001: ldc.i4.0             // Push 0 onto the stack as int32
    IL_0002: stloc.0              // Pop a value from stack into local variable 0
    IL_0003: ldloc.0              // Load local variable 0 onto stack
    IL_0004: ldc.i4.1             // Push 1 onto the stack as int32
    IL_0005: beq.s IL_000a        // Branch to target if equal, short form
    IL_0007: ldc.i4.2             // Push 2 onto the stack as int32
    IL_0008: br.s IL_000b         // Branch to target, short form
    IL_000a: ldc.i4.1             // Push 1 onto the stack as int32
    IL_000b: stloc.0              // Pop a value from stack into local variable 0
    IL_000c: ret                  // Return from method, possibly with a value
} // end of method Exemplo::Main

Can be observed in the Sharplab.

Therefore there is difference. The difference is only syntactic. But in previous version of this reply there was no difference. So it is implementation detail, can change from one version to another.

Contrary to popular belief, the version using the conditional operator may be more efficient.

But it’s not that simple. This may not be valid in other situations. I made a simple example. The only way to know what’s really going to happen and if it’s going to have the same performance is to measure it. It is checking whether to generate the same code in its exact real situation in the compiler version that is used.

And what’s more, the Jitter can make more optimizations and reverse the situation or leave under the same conditions.

See another example of comparison in English.

You can check the raw IL code with the ildasm.exe that comes with Visual Studio, or you can use another decompiler like Ilspy, the dotPeek, the .NET Reflector or the Justdecompile.

You must choose what is better to give understanding for what you want. If you need to use a conditional operator in a complex expression it can become unreadable. On the other hand create multiple lines in one if to do a simple operation can also be an exaggeration. A hint to improve the readability of the conditional operator and to make it clear that you are mounting an expression is to place parentheses around the complete expression (the three operands as one thing). Of course there are situations that even this does not help.

If there is side effect (change of status), this needs to be clear in the code. It seems to me that in the cases I have presented this is clear. But there are cases where the code can make it difficult to read the side effect. You should avoid hiding possible misunderstandings in the code. The ternary operator is more prone to this. But neither should we run away from it at all costs. Relevance should be observed in the specific case.

Good example:

int resultado = Check() ? 1 : 0;

Bad example:

int resultado = Check1() ? 1 : Check2() ? 1 : Check3() ? 1 : 0;

Although this example can be improved:

int resultado = Check1() ? 1 :
                Check2() ? 1 :
                Check3() ? 1 :
                           0;

One of the advantages of using the conditional operator instead of the if is the reduction of duplicate code. It is good to keep the concision. But this must not be to the detriment of the readability of the code. More performance for one side or the other is no advantage. The gain will certainly be small even in the most extraordinary situations. If you really need this possible small performance gain, C# is not the appropriate language.

The Resharper is a great tool (almost mandatory) and gives great suggestions, but it does not code for you. The programmer is always needed to give context to the code. Resharper is no smarter than you and he doesn’t know if his code is really going to get any better the way he suggests. He hints, you decide.

I put in the Github for future reference.

  • perfect answer, thank you, about the Resharper I know he does not program, but as he insisted saying the ternary operator was better I thought it would be more performatic, but his compilation code makes it clear that in the end it is identical.

  • 1

    Of course, just to make it clear to everyone, I didn’t just answer to you.

  • 1

    @Augustovasques has some, I’ve even created a talk, but the beginner does not want to know anything, and the most experienced or already know these things, or they are pseudo experienced, IE, are beginners with work time, and also do not care about it. That’s how the market is, it breaks my heart.

0

As I know Resharper analyzes the "simplicity" of the if and suggests the expression "?:" to replace the if. I believe I’ve won in performance, yes, but nothing so significant.

But consider one thing, analyze the full reading of your code and see if it’s readable to other programmers. The excessive use of this expression can cause confusion in the reading of the code, hindering a future reading for maintenance in the application.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.