NOTE: This is different than the proposed duplicates as this deals with an argument rather than a value. The behavior and applicable scenarios are essentially different.
Say we have SomeEnum
and have a switch statement handling it like:
enum SomeEnum
{
One,
Two,
}
void someFunc(SomeEnum value)
{
switch(value)
{
case SomeEnum.One:
...
break;
case SomeEnum.Two:
...
break;
default:
throw new ??????Exception("Unhandled value: " + value.ToString());
}
}
As you see we handle all possible enum values but still keep a default throwing an exception in case a new member gets added and we want to make sure we are aware of the missing handling.
My question is: what's the right exception in such circumstances where you want to notify that the given code path is not handled/implemented or should have never been visited? We used to use NotImplementedException
but it doesn't seem to be the right fit. Our next candidate is InvalidOperationException
but the term doesn't sound right. What's the right one and why?
EDIT: C# 8.0 introduced switch expressions which produce compiler warnings for non-exahustive switch statements. That's another reason why you should use switch expressions over switch statements whenever applicable. The same function can be written in a safer way like:
void someFunc(SomeEnum value)
{
_ = value switch
{
SomeEnum.One => ....,
SomeEnum.Two => ....,
}
}
When a new member gets added to SomeEnum
, the compiler will show the warning "CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern 'EnumHandling.SomeEnum.Three' is not covered." for the switch expression which makes it way easier to catch potential bugs.
If an exception occurs inside the switch, then it's fine. The one reasonably standard place you might throw inside a switch statement is in the default case. If reaching that case indicates invalid input, then it's reasonable to throw an exception.
Putting the exception in the default-statement makes clear to the reader that the code is never supposed to get past the switch-statement. Otherwise they would have to check if really all of the enum values are in the switch.
ArgumentException
looks the most correct to me in this instance (though is not defined in the BCL).
There is a specialized exception for enum arguments - InvalidEnumArgumentException:
The exception thrown when using invalid arguments that are enumerators.
An alternative is ArgumentOutOfRangeException:
The exception that is thrown when the value of an argument is outside the allowable range of values as defined by the invoked method.
The logic for using these is that the passed in argument (value
) is not valid as far as someFunc
is concerned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With