The .NET Framework has a lot of pre-defined exceptions. For example, if an invalid parameter was passed to my method, I'm supposed to raise an ArgumentException (or ArgumentNullException, if the paramter was null). If a method is called that is invalid for the current object state, I'm supposed to raise an InvalidOperationException.
Is there some pre-defined exception for the "this code should never be reached" case? Here's an example:
void myMethod() {
int a;
... /* Some complex code that manipulates a. In the end, "a" can only be 1 or 2. */
switch (a) {
case 1: ...
case 2: ...
default: // just an extra sanity check
// Oops, we should never be here.
// There's apparently some bug in the code above.
throw new ThereIsABugInTheCodeException();
}
}
I don't think creating my own exception for such a rare case is justified. On the other hand, just throwing Exception is discouraged as well. I guess some kind of AssertionFailedException would be appropriate, but I did not find any in the .net Framework. (Note that Trace.Assert does not throw an exception, so that's not an option either.)
EDIT: To clarify: a is NOT an argument. Let me rephrase the question to make it clearer: In the middle of a method I do a sanity check (just to make sure, it should not be necessary if the code in the beginning of the method is correct). I find out the sanity check fails and would like to throw an exception. Which one do I throw? I don't think that ArgumentException is the correct answer, since ArgumentException should only be thrown if the caller of the method did something wrong. That is not the case here. The method itself realizes at runtime that it contains a bug.
Oddly enough the .NET Framework does not contain an exception to describe logical or internal errors. But on the other hand the .NET Framework should have a quality level where there shouldn't be a need to throw exceptions for internal errors. Would you trust a .NET API call that in the documentation stated that it might throw an InternalErrorException? Remember that exceptions derived from SystemException are exceptions used by the framework. It can be useful to reuse these exceptions but the exceptions were created for use by the framework and not your framework/application.
You can use ArgumentException, ArgumentNullException, ArgumentOufOfRangeException, NotSupportedException and InvalidOperationException in cases where your methods a called in an unexpected way.
You can also create your own InternalErrorException.
Microsofts more general solution to this problem is Code Contracts. Many contracts can be checked at compile time helping you produce better code and you can use Contract.Assume and Contract.Assert to verify conditions in your code. The rewriter will insert code that will throw a ContractException if the condition is false. This exception has been crafted in a special way (from the DevLabs Code Contracts documentation):
The ContractException type is not a public type and is emitted as a nested private type into each assembly for which runtime contract checking is enabled. It is thus not possible to write catch handlers catching only ContractException. Contract exceptions can thus only be handled as part of a general exception backstop. The rationale for this design is that programs should not contain control logic that depends on contract failures, just like programs should not catch ArgumentNullException or similar validation exceptions.
For the case you show I would also go with an ArgumentException, possibly an ArgumentOutOfRangeException.
Edit I didn't look closely enough and though the switch was on method argument, but apparently it isn't. So an ArgumentException is probably, not applicable. The rest of my answer stands as it is.
However, there really might be cases when program state is totally unexpected. For such cases I wouldn't even use an exception (that can be caught). In such cases one could argue, that security and data integrity is at stake, so the only sensible thing is to exit the application as fast as possible (to minimize the chance of corrupting state further).
You should probably think about using Debug.Assert or Trace.Assert in that case, or roll your own handler that essentially calls Environment.FailFast.
Whether such behavior is correct or acceptable for your application is a decision you have to make.
Update: You might also want to look into Code Contracts. Which AFAIK, can be tailored in their runtime behavior to either throw exceptions, abort the process or do nothing.
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