异常引发

当某个成员无法成功执行它应执行的操作时,将会引发异常。 这称为“执行失败”。 例如,如果 Connect 方法无法连接到指定的远程终结点,则这就是一个执行故障,将有一个异常被引发。

下列准则可帮助确保在适当时引发异常。

不要返回错误代码。 异常是报告框架中的错误的主要手段。

异常设计准则 讨论了使用异常的许多好处。

通过引发异常来报告执行故障。 如果某一成员无法按预期方式成功执行,则应将这种情况视为一个执行故障并引发一个异常。

如果代码遇到继续执行则不安全的情况,应考虑通过调用 System.Environment.FailFast(System.String)(.NET Framework 2.0 中的一种功能)来终止进程,而不是引发异常。

尽可能不对正常控制流使用异常。 除了系统故障及可能导致争用状态的操作之外,框架设计人员还应设计一些 API 以便用户可以编写不引发异常的代码。 例如,可以提供一种在调用成员之前检查前提条件的方法,以便用户可以编写不引发异常的代码。

下面的代码示例演示如何进行测试以防止在消息字符串为 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 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 Doer
{
    // Method that can potential throw exceptions often.
    public static void ProcessMessage(string message)
    {
        if (message == null)
        {
            throw new ArgumentNullException("message");
        }
    }
    // Other methods...
}

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 Doer
{
public:
    // Method that can potential throw exceptions often.
    static void ProcessMessage(String^ message)
    {
        if (message == nullptr)
        {
            throw gcnew ArgumentNullException("message");
       }
    }
    // Other methods...
};

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);
            }
        }
    }
};

有关可以减少异常引发数量的设计方案的其他信息,请参见 异常和性能

考虑引发异常的性能影响。

记录公共可调用的成员因成员协定冲突(而不是系统故障)而引发的所有异常,并将这些异常视为协定的一部分。 包含在协定中的异常不应从一个版本更改到下一个版本。

不要包含可以根据某一选项引发或不引发异常的公共成员。

例如,不要定义如下所示的成员:

Private Function ParseUri(ByVal uriValue As String, ByVal throwOnError As Boolean) As Uri
Uri ParseUri(string uriValue, bool throwOnError)
Uri^ ParseUri(String^ uriValue, bool throwOnError)

不要包含将异常作为返回值或输出参数返回的公共成员。

此项准则适用于公共可见的成员。 使用私有帮助器方法构造和初始化异常是可以接受的。

考虑使用异常生成器方法。 从不同的位置引发同一异常会经常发生。 为了避免代码膨胀,请使用帮助器方法创建异常并初始化其属性。

帮助器方法不得引发异常,否则堆栈跟踪将无法正确反映出引发异常的调用堆栈。

不要从异常筛选器块中引发异常。 当异常筛选器引发异常时,公共语言运行时 (CLR) 将捕获该异常,然后该筛选器返回 false。 此行为与筛选器显式执行和返回 false 的行为无法区分,因此很难调试。

有些语言(如 C#)不支持异常筛选器。

避免从 finally 块中显式引发异常。 可以接受因调用引发异常的方法而隐式引发的异常。

部分版权所有 2005 Microsoft Corporation。 保留所有权利。

部分版权所有 Addison-Wesley Corporation。 保留所有权利。

设计指引的详细信息,请参阅"框架设计准则: 公约、 成语和可重复使用的模式。网络图书馆"书 Krzysztof Cwalina 和布拉德 · 艾布拉姆斯,2005年艾迪生 - 韦斯利,发表。

请参见

概念

选择要引发的正确异常类型

其他资源

类库开发的设计准则

异常设计准则