异常和性能
引发异常可能会对性能造成不良的影响。 对于经常性执行失败的代码,可以使用设计模式最大限度地减少性能问题。 本主题描述两种设计模式,在异常可能会严重影响性能时使用这两种模式很有帮助。
不要由于担心异常可能会对性能造成不良影响而使用错误代码。
利用设计来减少性能问题。 在本主题中描述了两种设计模式。
对于可能在常见方案中引发异常的成员,可以考虑使用 Tester-Doer 模式来避免与异常相关的性能问题。
Tester-doer 模式将分为了调用,可能会引发异常,分成两个部分: 一种测试仪和实干家。 Tester 对可能导致 Doer 引发异常的状态执行测试。 测试恰好插入在引发异常的代码之前,从而防范异常发生。
下面的代码示例演示此模式的 Doer 部分。 该示例包含一个方法,在向该方法传递 null(在 Visual Basic 中为 Nothing)值时该方法将引发异常。 如果频繁地调用该方法,就可能会对性能造成不良影响。
Public Class Doer
' Method that can potential throw exceptions often.
Public Shared Sub ProcessMessage(ByVal message As String)
If (message = Nothing) Then
Throw New ArgumentNullException("message")
End If
End Sub
' Other methods...
End Class
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...
}
public ref class Doer
{
public:
// Method that can potential throw exceptions often.
static void ProcessMessage(String^ message)
{
if (message == nullptr)
{
throw gcnew ArgumentNullException("message");
}
}
// Other methods...
};
下面的代码示例演示此模式的 Tester 部分。 该方法利用一个测试来避免在 Doer 将引发异常时调用 Doer (ProcessMessage)。
Public Class Tester
Public Shared Sub TesterDoer(ByVal messages As ICollection(Of String))
For Each message As String In messages
' Test to ensure that the call
' won't cause the exception.
If (Not (message) Is Nothing) Then
Doer.ProcessMessage(message)
End If
Next
End Sub
End Class
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);
}
}
}
}
public ref class Tester
{
public:
static void TesterDoer(ICollection<String^>^ messages)
{
for each (String^ message in messages)
{
// Test to ensure that the call
// won't cause the exception.
if (message != nullptr)
{
Doer::ProcessMessage(message);
}
}
}
};
注意,当在测试涉及可变对象的多线程应用程序中使用该模式时,必须解决可能出现的争用状态问题。 线程可以在测试之后且 Doer 执行之前更改可变对象的状态。 使用线程同步技术可以解决这些问题。
对于可能在常见方案中引发异常的成员,可以考虑使用 TryParse 模式来避免与异常相关的性能问题。
若要实现 TryParse 模式,需要为执行可在常见方案中引发异常的操作提供两种不同的方法。 第一种方法 X, 执行该操作并在适当时引发异常。 第二种方法 TryX, 不引发异常,而是返回一个 Boolean 值以指示成功还是失败。 由对 TryX 的成功调用所返回的任何数据都通过使用 out(在 Visual Basic 中为 ByRef)参数予以返回。 Parse 和 TryParse 方法就是此模式的示例。
为每个使用 TryParse 模式的成员提供一个引发异常的成员。
只提供 TryX 方法几乎在任何时候都不是正确的设计,因为使用该方法需要了解 out 参数。 此外,对于大多数常见方案来说,异常对性能的影响不会构成问题;因此应在大多数常见方案中提供易于使用的方法。
部分版权所有 2005 Microsoft Corporation。 保留所有权利。
部分版权所有 Addison-Wesley Corporation。 保留所有权利。
设计指引的详细信息,请参阅"框架设计准则: 公约、 成语和可重复使用的模式。网络图书馆"书 Krzysztof Cwalina 和布拉德 · 艾布拉姆斯,2005年艾迪生 - 韦斯利,发表。