Exceptions and Performance
Throwing exceptions can negatively impact performance. For code that routinely fails, you can use design patterns to minimize performance issues. This topic describes two design patterns that are useful when exceptions might significantly impact performance.
Do not use error codes because of concerns that exceptions might affect performance negatively.
Use design to mitigate performance issues. Two patterns are described in this topic.
Consider the Tester-Doer pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions.
The Tester-Doer pattern divides a call that might throw exceptions into two parts: a Tester and a Doer. The Tester performs a test for the state that can cause the Doer to throw an exception. The test is inserted just before the code that throws the exception, thereby guarding against the exception.
The following code example shows the Doer half of this pattern. The example contains a method that throws an exception when it is passed a null (Nothing in Visual Basic) value. If this method is called often, it could negatively impact performance.
public class Doer
{
// Method that can potential throw exceptions often.
public static void ProcessMessage(string message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
}
// Other methods...
}
The following code example shows the Tester part of this pattern. The method uses a test to prevent the call to the Doer (ProcessMessage
) when the Doer would throw an exception.
public class Tester
{
public static void TesterDoer(ICollection<string> messages)
{
foreach (string message in messages)
{
// Test to ensure that the call
// won't cause the exception.
if (message != null)
{
Doer.ProcessMessage(message);
}
}
}
}
Note that you must address potential race conditions if you use this pattern in a multithreaded application where the test involves a mutable object. A thread can change the state of the mutable object after the test but before the Doer executes. Use thread synchronization techniques to address these issues.
Consider the TryParse pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions.
To implement The TryParse pattern, you provide two different methods for performing an operation that can throw exceptions in common scenarios. The first method, X*,* does the operation and throws the exception when appropriate. The second method, TryX*,* does not throw the exception, but instead returns a Boolean value indicating success or failure. Any data returned by a successful call to TryX is returned using an out (ByRef in Visual Basic) parameter. The Parse and TryParse methods are examples of this pattern.
Do provide an exception-throwing member for each member using the TryParse pattern.
It is almost always not correct design to provide only the TryX method because it requires understanding out parameters. Also, the performance impact of exceptions is not an issue for most common scenarios; you should provide methods that are easy to use in most common scenarios.
Portions Copyright 2005 Microsoft Corporation. All rights reserved.
Portions Copyright Addison-Wesley Corporation. All rights reserved.
For more information on design guidelines, see the "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" book by Krzysztof Cwalina and Brad Abrams, published by Addison-Wesley, 2005.
See Also
Other Resources
Design Guidelines for Developing Class Libraries
Design Guidelines for Exceptions