Design Guidelines Update: Exception Throwing

Exception throwing guidelines described in this section require a good definition of the meaning of execution failure. Execution failure occurs whenever a member cannot do what it was designed to do (what the member name implies). For example, if OpenFile method cannot return an opened file handle to the caller, it would be considered an execution failure.

Most developers have become comfortable with using exceptions for hard error cases such as division by zero or null references. In the Framework, exceptions are used for both hard errors and logical errors. At first, it can be difficult to embrace exception handling as the means of reporting all functional failures. However, it is important to design all public methods of a framework to report method-failures by throwing an exception.

There are a variety of excuses for not using exceptions, but most boil down to the two perceptions that exception handling syntax is undesirable, so returning an error code is somehow preferable, or that a thrown exception does not perform as well asreturning an error code. The performance concerns are addressed in the performance section below. The concern over syntax is largely a matter of familiarity and should not be a consideration. As an API designer we should not make assumptions about the familiarity of the application developers consuming our code.

ýDo not return error codes. Exceptions are the primary means of reporting errors in frameworks.

þDo report execution failures by throwing exceptions. If a member cannot successfully do what is designed to do, it should be considered an execution failure and an exception should be thrown.

þConsider terminating the process by calling System.Environment.FailFast (.NET Framework 2.0 feature) instead of throwing an exception, if your code encounters a situation where it is unsafe for further execution.

ýDo not use exceptions for normal flow of control. Except for system failures, there should generally be a way to write code that avoids exceptions being thrown. For example, you can provide a way to check preconditions before calling a member to allow users to write code that does not throw exceptions.

ICollection<int> collection = …

if(!collection.IsReadOnly){

collection.Add(additionalNumber);

}

The member used to check preconditions of another member is often referred to as a tester and the member that actually does the work is called a doer. See performance section below for more information on the Tester-Doer Pattern.

There are cases when the Tester-Doer pattern may have an unacceptable performance overhead. In such cases the so called TryParse Pattern (see section below) should be used.

þDo document all exceptions thrown by publicly callable members because of a violation of the member contract (rather than a system failure) and treat them as part of your contract. Exceptions that are a part of the contract should not change from one version to the next.

ýDo not have public members that can either throw or not based on some option.

Type GetType(string name, bool throwOnError)

ýDo not have public members that return exceptions as the return value or an out parameter.

þDo set all the relevant properties of the exception you throw.

þConsider using exception builder methods. It is common to throw the same exception from different places. To avoid code bloat, use helper methods that create exceptions and initialize their properties. For example:

class File{

string fileName;

public byte[] Read(int bytes){

if (!ReadFile(handle, bytes))

throw NewFileIOException(...);

}

FileException NewFileException(...){

string description = // build localized string

return new FileException(description);

}

}

ýDo not throw exceptions from exception filter blocks. When an exception filter raises an exception, the exception is caught by the CLR, and the filter returns false. This behavior is indistinguishable from the filter executing and returning false explicitly and is therefore very difficult to debug.

þDo create and throw custom exceptions if you have an error condition that can be programmatically handled in a different way than any other existing exception. Otherwise, throw one of the existing exceptions.

ýDo not create and throw new exceptions just to have ‘your team's’ exception.

þDo throw the most specific (the most derived) exception that makes sense. For example, throw ArgumentNullException and not its base type ArgumentException if a null argument is passed.

One common concern related to exceptions is that if exceptions are used for code that routinely fails, the performance of the implementation will be unacceptable. This is a very valid concern. When a member throws an exception, its performance can be orders of magnitude slower. However, it is possible to achieve good performance while strictly adhering to the exception guidelines that disallow using error codes. Two patterns described in this section suggest ways to do this.

ýDo not use error codes because of concerns that exceptions might affect performance negatively.

Sometimes performance of an exception throwing member can be improved by breaking the member into two. Let’s look at the indexed property of the Dictionary class.

Dictionary<string,int> table = new Dictionary<string,int>();

…

int value = table[“key”];

The indexer throws if the key does not exist in the Dictionary. This can be a performance problem in scenarios where the lookup is expected to fail often. One of the ways to mitigate the problem is to test whether the key is in the dictionary before accessing the value.

Dictionary<string,int> table = new Dictionary<string,int>();

…

if(table.Contains(“key”)){

int value = table[“key”];

}

The member used to test a condition, in our example the method Contains, is referred to as the ‘tester’. The member used to perform a potentially throwing operation, in our example the indexer, is referred to as the ‘Doer’.

þConsider the Tester-Doer pattern for members which may throw exceptions in common scenarios to avoid performance problems related to exceptions.

For extremely performance demanding APIs, an even faster pattern than the Tester-Doer described in the previous section should be used. The pattern is to adjust the member name to make a well-defined test case a part of the member semantics. For example, DateTime defines a Parse method that throws if parsing of a string fails. It also defines a corresponding TryParse method which attempts to parse, but returns false if parsing is unsuccessful and returns the result of a successful parsing using an out parameter.

public struct DateTime {

public static DateTime Parse(string dateTime){

…

}

public static bool TryParse(string dateTime, out DateTime result){

…

}

}

When using this pattern, it is important to define the ‘try’ functionality in strict terms. If the member fails for any reason other than the well defined try, then the member must still throw.

þConsider the TryParse pattern for members which may throw exceptions in common scenarios to avoid performance problems related to exceptions.

þDo provide an exception-throwing member for each member using the TryParse pattern.

&quot;Do not create and throw new exceptions just to have ‘your team’s’ exception.&quot;
<br>
<br>I was planning to do exactly that so we can identify exceptions thrown by our own code.
<br>
<br>Could you explain why this is a bad idea ?
<br>
<br>thanks.

Question on AgumentNullException.
<br>
<br>What exception to throw if my method does not allow &quot;&quot; (empty string) and such argument was passed in?
<br>
<br>In some place of CLR I have seen ArgumentNullException, but String.Empty is definitely not null. What is the guideline here?
<br>
<br>Please claim this option to official document, that all developers have to deal same way.

&quot;Do not create and throw new exceptions just to have ‘your team’s’ exception.&quot;
<br>
<br>Could you explain why ?
<br>
<br>We were planning to do this so we can identify the exceptions thrown by our code.
<br>

Jacques Troux: it is phylosophical discussion. Miguel de Icaza — leader of Mono, a.k.a. .NET for Linux — Miguel votes for error codes in some of his old messages. And you can find the interview with Anders Heilsberg — author of C# — that expressively votes for exceptions.
<br>
<br>All .NET ideology built with exceptions, and it is extrmely important for security and stability.

Jeroen, you’re correct about the behavior.
<br>
<br>I wouldn’t recommend following the pattern that Thread.Abort() uses. (Note: I wouldn’t recommend suspending and asynchronously aborting threads either, but that’s a wildly separate topic. :))
<br>
<br>The behavior is strange. It succeeds at provoking an abort, but does throw an exception.
<br>
<br>I wish we could change it, but it’s been that way since 1.0.

"Do not use error codes because of concerns that exceptions might affect performance negatively."

is violated by the TryParse pattern. The TryParse pattern is worded nicely, but still clearly uses an error code to indicate success or failure.

This contradiction, and the confusion that comes with it, disappear if you qualify the first rule with "except in extremely performance demanding APIs," and then suggest to "Do use" the TryParse pattern for these situations.

System.Environment.FailFast offers the user a chance to send an error report, then terminates the process. (It’s the nicer managed equivalent to calling ExitProcess when you decide you really can’t go on.) If you’re writing a class library you probably don’t want to use FailFast–at least not if you like having customers :-D. If you’re writing an application, though, it often makes sense if you really want the process to die. Exceptions can be caught; FailFast just kills the process right away.

Here’s how I think about the performance rule and Parse vs. TryParse:
<br>
<br>Parse says it’s going to parse something. “Failure” means it couldn’t parse it. So exceptions from Parse could include exceptions because what you passed to it wasn’t parseable. The return value is the result of the operation—the parsed value.
<br>
<br>TryParse says it’s going to try to parse something. “Failure” means that it wasn’t even able to _try_ to parse the thing. Thus the only kinds of exceptions you’re going to get out of TryParse are things like OutOfMemory from JITting or allocating buffers before it even gets a chance to look at the string to be parsed. (You wouldn’t expect to get an exception because the value wasn’t parseable…the point is the method said it was going to try, and it did try. It did what it said it would, so no exception needed.) TryParse really has two results—was the thing parseable, and if so the parsed value.
<br>

It isn’t clear whether you prohibit exceptions from /containing/ error codes (as a property). This ought to be allowed, because in some circumstances your only other options are (a) having a huge set of different exception types or (b) parsing the exception message to figure out what exactly happened.
<br>An example of this problem is XmlException, which can be thrown for 1000 different reasons and needs an error code property to distinguish it.

The use of the word Throw has mulitple meanings in .net. As a result the article is somewhat ambiguous. In object oriented design, the standard of an object is that it is responsible for it’s own function. Therefore, it is my understanding that objects and or methods within, should not Throw anything. Instead they should handle the exception and move on. Does your term throw mean "Handle the exception and inform the user?"

I agree that the term “throwing” is a bit ambiguous. It means either executing the throw statement or allowing an exception propagate out of a publicly callable API.

I am not sure why you interpret throwing as handling exceptions and showing them to users. Could you point me to any particular statements that might imply so?

As to objects handling exceptions and moving on, I think it’s only true for some kinds of exceptions. There are others that simply cannot be handled because the object does not have enough context to know how to fix the state of the system in the exception handler so it could continue safely. Those can sometimes be handled higher up on the stack, but in some cases they cannot be handled at all, and the best approach is to record as much information as possible and shut down the process/app domain.

JP, please feel free to email me directly (kcwalina_at_microsoft.dot_com) if you’d like to talk about this more.

Can you provide some guidance for how to structure a hierarchy of exception classes? I cannot find any information addressing this design issue. Should exceptions be grouped by the type of data that the error is associated with, or by the type of error. I think they should be organized by the type of error, but it is very difficult to group errors this way. Thank you for any input you may have.

How would you recommend handling multiple ‘error’ types that are passed back from hardware devices? For example we are a driving a motor to cause movement, and the command ‘move()’ can fail for many reasons such as ‘HitEndStop’, "Stall", "PowerLoss". Currently we would do something like:

CError MoveTheDevice()

{

CError error = Move();

if (error.IsOk)

{

//… continue processing

}

return error; // to pass status higher up

}

Should we create lots of exception types and map the device errors to exception types?

or

should we throw an exception, having recorded the ‘error’ code somewhere – maybe as a ‘parameter’ within the exception.

Performance is a criteria to take into consideration, but one criteria that is not included in this article is code flow, throwing exceptions sometimes makes you code flow nicer than trying to exit your method earlier and trying to clean up, when you finally statement could handle that, returning error codes from your method when it happens, etc…. I assume that this guidelines apply to exceptions that could occur in .net system classes, but what about classes that I create? If have not seen any issues with performance in throwing exceptions in my production application…It has made the flow of my program much cleaner and easier to understand.

In rare cases it’s better to communicate errors through events. This is true mainly for asynchronous APIs where the original caller thread is long doing some other things and we can not throw to that thread anymore.