Always Identical Outputs? Switch Statement vs. Switch Expression

, ,

Are these two statements identical in what they return?

public object Switcher(bool flag) 
{
  switch (flag) {
    case true:
      return 1;
    case false:
     return 10.5;
  }
}
public object Switcher(bool flag) 
{
  return flag switch {
    true => 1,
    false => 10.5
  };
}

No.

TestResult –
Switch Statement
Result –
Switch Expression
Assert.Equal(1, x.Switcher(true));PassFail – Error Message:
Assert.Equal() Failure
Expected: 1 (System.Int32)
Actual: 1 (System.Double)
Assert.Equal(10.5, x.Switcher(false));PassPass

Scratching your head trying to find the difference? The logic in both looks identical. Arguably, it is.

The difference is in the type of the values that are returned. The switch statement shown will return an integer or a double, depending on flag. In contrast, this switch expression always returns a double! This is true even when flag is true: in that case, 1 will be returned, but not an integer 1 (as it was defined in code); rather, the 1 will have been converted to a double.

After thinking about it for a moment, this probably makes sense. The switch statement has two different return expressions. Separate expression can each be of (a.k.a. produce a value of) a different type. This switch statement’s return 1 returns an integer while its return 10.5 returns a double. Two different expressions, two different types.

In contrast, the switch expression is a single expression. What is its type? The answer has to be consistent; it can’t conditionally be one of two different types. Rather, it’s the “best common type” of the various switch arms’ types. The best common type between “1” (integer) and “10.5” (double) is double, so this switch expression always returns a double. When flag is true, the switch arm which outputs the integer “1” is chosen, but that “1” is converted to a double before it is returned by the expression.

A subtle different to be aware of for those (rare?) cases where you use the same switch to return different value types. Refactoring this kind of switch statement into an expression won’t result in exactly the same behavior as the original statement.

Leave a Reply

Your email address will not be published. Required fields are marked *