Checked Cast vs Convert in C#

Let’s say we want to convert int to short with a bounds check. Is there a difference between checked((short)x) and Convert.ToInt16(x)?

Behavior

The behavior is the same for both methods: if the value is out of bounds, an OverflowException is thrown.

Performance

Benchmark results:

|      Method |        Val |          Mean |      Error |     StdDev | Ratio | RatioSD |
|------------ |----------- |--------------:|-----------:|-----------:|------:|--------:|
| CheckedCast |          1 |     0.3265 ns |  0.0030 ns |  0.0028 ns |  1.00 |    0.00 |
|   ConvertTo |          1 |     1.1499 ns |  0.0044 ns |  0.0042 ns |  3.52 |    0.03 |
|             |            |               |            |            |       |         |
| CheckedCast | 2147483647 | 6,430.8317 ns | 10.7705 ns | 10.0747 ns |  1.00 |    0.00 |
|   ConvertTo | 2147483647 | 6,405.4382 ns | 20.2827 ns | 18.9725 ns |  1.00 |    0.00 |

Checked cast is 3.5 times faster when there is no exception.

Generated Code

Checked cast is compiled into a single conv.ovf.i2 instruction.

Convert.ToInt16 method uses an explicit bounds check and then an unchecked cast (conv.i2):

public static short ToInt16(int value)
{
    if (value < short.MinValue || value > short.MaxValue) ThrowInt16OverflowException();
    return (short)value;
}

Conclusion

With Convert.ToInt16(x) it is not immediately clear if the bounds check is performed or not.

Checked cast is faster, generates less code, and carries the intent better.

Written on July 13, 2023