Once compiled, is there a significant difference between if statements and switch statements? I wanted to find out. Thanks to /u/sauce-control, I played with this example in the very awesome sharplab.io tool.

Today’s sample program:

class Program
{
    private const string STR_HELLO = "Hello";
    private const string STR_HELLO_RESPONSE = "Hello to you too!";
    private const string STR_GOODBYE = "Goodbye";
    private const string STR_GOODBYE_RESPONSE = "Goodbye, see you soon!";
    private const string STR_UNKNOWN_RESPONSE = "I don't understand. Sorry.";

    static void Main(string[] args)
    {
        var input1 = Console.ReadLine();

        PrintResponse(input1);
        PrintResponse_If(input1);
    }

    private static void PrintResponse(string input1)
    {
        switch (input1)
        {
            case STR_HELLO:
                Console.WriteLine(STR_HELLO_RESPONSE);
                break;
            case STR_GOODBYE:
                Console.WriteLine(STR_GOODBYE_RESPONSE);
                break;
            default:
                Console.WriteLine(STR_UNKNOWN_RESPONSE);
                break;
        }
    }

    private static void PrintResponse_If(string input1)
    {
        if (input1 == STR_HELLO)
        {
            Console.WriteLine(STR_HELLO_RESPONSE);
        }
        else if (input1 == STR_GOODBYE)
        {
            Console.WriteLine(STR_GOODBYE_RESPONSE);
        }
        else
        {
            Console.WriteLine(STR_UNKNOWN_RESPONSE);
        }
    }
}

Let’s first look at the switch statement IL that is generated.IL for Switch Statement

IL_0000: ldarg.0
// This is interesting - in the switch version, there is a quick
// check to see if the string is null. If it is null, go to the
// default branch first.
IL_0001: brfalse.s IL_0035

// Check to see if the input string == "Hello"
// 
IL_0003: ldarg.0
IL_0004: ldstr "Hello"
IL_0009: call bool [mscorlib]System.String::op_Equality(string, string)
IL_000e: brtrue.s IL_001f

// Check to see if the input string == "Goodbye"
// 
IL_0010: ldarg.0
IL_0011: ldstr "Goodbye"
IL_0016: call bool [mscorlib]System.String::op_Equality(string, string)
IL_001b: brtrue.s IL_002a

// Unconditionally branch to the default. Why? Both the hello/goodbye
// comparisons use a brtrue to branch if the two strings are equal.
IL_001d: br.s IL_0035

IL_001f: ldstr "Hello to you too!"
IL_0024: call void [mscorlib]System.Console::WriteLine(string)
IL_0029: ret

IL_002a: ldstr "Goodbye, see you soon!"
IL_002f: call void [mscorlib]System.Console::WriteLine(string)
IL_0034: ret

IL_0035: ldstr "I don't understand. Sorry."
IL_003a: call void [mscorlib]System.Console::WriteLine(string)
IL_003f: ret

The switch version uses the string equality operator to see if the strings are equal, then branches accordingly. It also has an early check to see if the string that was passed in is null.IL for if Statement

IL_0000: ldarg.0
IL_0001: ldstr "Hello"
IL_0006: call bool [mscorlib]System.String::op_Equality(string, string)
IL_000b: brfalse.s IL_0018

IL_000d: ldstr "Hello to you too!"
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
IL_0017: ret

IL_0018: ldarg.0
IL_0019: ldstr "Goodbye"
IL_001e: call bool [mscorlib]System.String::op_Equality(string, string)
IL_0023: brfalse.s IL_0030

IL_0025: ldstr "Goodbye, see you soon!"
IL_002a: call void [mscorlib]System.Console::WriteLine(string)
IL_002f: ret

IL_0030: ldstr "I don't understand. Sorry."
IL_0035: call void [mscorlib]System.Console::WriteLine(string)
IL_003a: ret

I was expecting these two versions to be exactly the same. What’s neat about the IF version is that if an equality comparison is false, the method will branch to the next condition to check. This is almost an exact translation of the if-statement code in C# to IL.

Which version is “better“? The code is just about equal in both cases, and when you compare the JIT’d assembly, the difference is even smaller. One version does branch-if-true, one does branch-if-false.

I doubt that one could spot the difference in 99% of scenarios. The only time I see it being less expensive is if you have a lot of null strings to check, but even then you could write an if statement to capture that scenario.

Published by Elias

Elias Puurunen is a versatile entrepreneur and President of Northern HCI Solutions Inc., an IT consulting firm which has worked with Fortune 500 companies, governments, and startups. He has spoken at conferences in Canada and the United States and has been published around the world. Part of his work led to an agreement between the Canadian Government and Siemens Canada, creating jobs and investment into green infrastructure. His company's event management app, the Tractus Event Passport connects people at conferences, seminars and symposiums across Canada. Today he is a consultant and advisor to technology firms and government organizations. He lectures at the University of Waterloo on Coding for Policy Analysis for the School of Public Policy. He is the author of Beyond Passwords: Secure Your Business, a cyber-security book for small business owners.

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: