Design Guidelines Update: Exception Throwing

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 as  returning 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.

þ     Consider performance implications of throwing exceptions. See section below for details.

þ     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.

ý     Avoid explicitly throwing exceptions from finally blocks. Implicitly thrown exceptions resulting from calling methods that throw are acceptable. 

1.1.1 Choosing the Right Type of Exception to Throw

þ     Consider throwing existing exceptions residing in the System namespaces instead of creating custom exception types.

þ     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.

1.2 Exceptions and Performance

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.

Tester-Doer Pattern

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.

TryParse Pattern

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.

Published 16 March 05 11:44 by kcwalina
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# BCLTeam's WebLog said on March 16, 2005 10:51 AM:
# Rolando said on March 16, 2005 12:00 PM:
&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.
# damien morton said on March 16, 2005 12:48 PM:
Python uses what is called the "samurai principle" for determining when to throw exceptions:

Return a meaningfull and useable result or else throw an exception.

I find that the standard prescription "exceptions are for exceptional circumstances" doesnt give much guidance, and welcome these new guidelines.
# Richard Murillo's Blog said on March 16, 2005 12:56 PM:
# LA.Net said on March 16, 2005 1:26 PM:
# Jacques Troux said on March 16, 2005 6:54 PM:
"Do not return error codes. Exceptions are the primary means of reporting errors in frameworks."

Blech. One more reason for me to stay away from .net.
# Jeroen Frijters said on March 17, 2005 6:22 AM:
So what do you make of Thread.Abort() that (on Whidbey, if the thread is suspended) throws an exception *and* schedules an abort?
# mihailik said on March 17, 2005 9:25 AM:
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.
# Rolando said on March 17, 2005 9:25 AM:
&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>
# mihailik said on March 17, 2005 9:31 AM:
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.
# Joe Duffy said on March 17, 2005 4:13 PM:
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.
# David M. Kean said on March 18, 2005 1:04 AM:
What does FailFast do? I can't find any documentation on it.
# Jeffrey Sax said on March 18, 2005 1:12 PM:
This guideline is mostly excellent, but confusing in one respect.

This performance rule:

"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.
# Jonathan Keljo [MS] said on March 18, 2005 1:41 PM:
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.
# Jonathan Keljo [MS] said on March 18, 2005 3:26 PM:
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>
# Vincent said on March 20, 2005 12:37 PM:
Hello,

FYI: your blog renders completely wrong in Firefox.
# Brad Abrams said on March 28, 2005 8:05 PM:
# Goran Pušić said on March 30, 2005 3:38 AM:
"FYI: your blog renders completely wrong in Firefox."

Um... In IE, too!?!? (IE6 on Wn2003)

OTOH, like the contents and the reasoning.
# dan said on March 30, 2005 10:14 PM:
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.
# Rolando Ramirez's WebLog said on April 5, 2005 11:31 AM:
# Rolando Ramirez's WebLog said on April 5, 2005 11:45 AM:
# Rolando Ramirez's WebLog said on April 5, 2005 12:25 PM:
# Rolando Ramirez's WebLog said on April 5, 2005 3:41 PM:
# Richard Murillo's Blog said on April 22, 2005 4:17 AM:
# Krzysztof Cwalina said on May 27, 2005 3:12 PM:
Recently somebody asked me to clarify one of the exception guidelines. They were asking whether it's...
# Wouter van Vugt said on August 10, 2005 2:15 AM:
# Jeff Stong said on June 6, 2006 2:21 PM:
In a recent post I mentioned the .NET framework design guidelines and that reminded me of a post by Krzyztof...
# Krzysztof Cwalina said on July 5, 2006 6:17 PM:
My last post about the ApplicationException resulted in some questions along the lines of “so, if not...
# JP said on July 29, 2006 10:49 AM:
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?"  
# kcwalina said on July 29, 2006 11:40 AM:
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.
# AlSki said on September 11, 2006 4:58 PM:
I came across this article on Exception Throwing by Krysztof Cwalina, and I didn't think its all very good advice... (See http://www.alski.net/software/Throwing+Exceptions.aspx)
# kcwalina said on September 14, 2006 7:36 PM:
AlSki, I posted a reply comment on your blog. I hope it clarifies some things. Please don't hesitate to email me at kcwalina_at_microsoft.com. I would be happy to discuss more detail.
# Chris said on January 30, 2007 9:39 AM:

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.

# NigelAston said on February 22, 2007 2:38 AM:

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.

# Sloan said on April 25, 2007 9:14 PM:

Krzysztof ,

Thank you for the great article.  Your ideas are clear and well laid out, and have helped tremendously.

NigelAston,

One way I deal with this scenario is using a "base" exception.

public abstract class HardwareFailureException : System.ApplicationException

public class HitEndStopException : HardwareFileException

public class PowerLossException : HardwareFileException

Then I believe you can just catch the HardwareFileException exception in your code.

Give it a try!

# CVC said on July 19, 2007 12:01 PM:

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.

# Pensando en asíncrono said on December 9, 2007 2:24 PM:

Buff... cuanto tiempo desde mi último post, entre estudiar y la medio-gripe que arrastro desde hace unas

# vtortola said on December 9, 2007 2:25 PM:

Buff... cuanto tiempo desde mi último post, entre estudiar y la medio-gripe que arrastro desde hace unas

# Still Learning » Blog Archive » Exception vs. Error Codes in C++ said on January 1, 2008 9:26 PM:

PingBack from http://imehta.com/blog-ketan/?p=15

# Ivara blogs said on January 9, 2008 7:20 PM:

&#352;odien &#160; Vakar Andrejs jau aizskāra tēmu, par kuru es jau pasen gribu uzrakstīt, bet kaut kā

# rakhs said on January 10, 2008 3:33 AM:

Gud one.

how we can throw exceptions from Appdomain "A" to appDomain "B".

Scenario:

In AppDomain "B" create a thread and from worker thread call a method in AppDomain "A" , which throws an exception. How we can catch this exception in AppDomain "B"

# Dum spiro, spero » Blog Archive » .NET Exceptions, Performance and Guidelines said on March 7, 2008 4:52 AM:

PingBack from http://blog.sanny.maniacs.nu/2008/03/07/net-exceptions-performance-and-guidelines/

# Janko's Blog said on March 8, 2008 7:22 AM:

Exception handling plays an important part of application management and user experience. If implemented

# Licantrop0 said on March 10, 2008 7:28 AM:

Hi Krzysztof, Iv'e bought your book and is one of my favourites.

I wanna ask if you can spend some word about the bad design to rise normal events (named "whateverError" or "whateverException") instead of throwing exceptions.

thanks.

# kcwalina said on March 11, 2008 2:23 PM:

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.

# Licantrop0 said on March 12, 2008 4:33 AM:

Thanks for your reply.

So except for multithreading environment, throwing exception is always the best way. I have many colleagues that sadly mix up event and exception so "you can manage what you prefer!" ... :|

Could you please write a little explanation about this in your new book?, so if "the .net guidelines bible said so", they can't complain... :)

regards!

# kcwalina said on March 17, 2008 12:52 PM:

I will try to clarify that in the book (2nd edition), but it already says that exceptions should be the default and other means of communicating errors should be very rare.

# Liste over exceptions i .NET said on March 26, 2008 6:11 AM:

PingBack from http://blog.todobom.dk/post/Liste-over-exceptions-i-NET.aspx

# GrabBag said on March 27, 2008 7:03 PM:

This post was originally published here . I recently posted on the out and ref keywords in C#, and mentioned

# Andrei Rinea said on May 25, 2008 10:16 AM:

A person asked above what should do in case the method called gets an empty string (String.Empty) and such a value is not acceptable?

Throwing an ArgumentNullException is not the best idea and ArgumentException might be a little too ambigous.

I always thought of ArgumentEmptyException as an exception class derived from ArgumentException.

What can you tell us about this issue?

# An example of the interplay between language features and library design, part one | abortive said on July 11, 2008 7:22 AM:

PingBack from http://www.abortive.com.cn/?p=31

# Luke Smith &raquo; Blog Archive &raquo; Sometimes you have to catch an exception said on July 31, 2008 4:43 PM:

PingBack from http://blog.lukesmith.net/index.php/2008/07/31/sometimes-you-have-to-catch-an-exception/

# 译时代 said on October 10, 2008 1:14 PM:

1.抛出异常(ExceptionThrowing)

抛出异常在这篇文章里被定义为是对执行失败时给出的定义。执行失败在任何时候都引出了一个被设计好的程序不去做它应该做的事情。例如,如果打开一个文...

# Favor structured exception handling | Anders Lybeckers Weblog! said on October 17, 2008 2:55 PM:

PingBack from http://www.lybecker.com/blog/2007/02/21/favor-structured-exception-handling/

# Best practice error handling? | keyongtech said on January 18, 2009 12:35 PM:

PingBack from http://www.keyongtech.com/551906-best-practice-error-handling

# VS said on January 19, 2009 12:47 AM:

mihailik:

AFAIK, there is no built in Exception class to check for empty arguments. What I can suggest is this:

In your method, do this:

if String.IsNullOrEmpty(param)

{

  throw new ArgumentException("The param cannot be null or an empty string.");

}

Can somebody comment?

# Exception Handling | keyongtech said on January 22, 2009 1:45 AM:

PingBack from http://www.keyongtech.com/433205-exception-handling

# Krzysztof Cwalina Design Guidelines Update Exception Throwing | fix my credit said on June 16, 2009 9:35 PM:

PingBack from http://fixmycrediteasily.info/story.php?id=10173

# Krzysztof Cwalina Design Guidelines Update Exception Throwing | Outdoor Decor said on June 19, 2009 12:17 AM:

PingBack from http://outdoordecoration.info/story.php?id=1835

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required
Page view tracker