原则

  • 不要使用返回状态值的方式表示异常。

  • 不要使用空catch,无法处理的异常要继续上抛。

约定

抛出异常

  • 在catch中继续上抛异常时,使用throw而不是throw ex,这样异常抛出位置不会被此catch截断。

  • 异常信息(Message)要文法正确,以结束符(句号)结尾。

  • 提供额外信息,例如抛出FileNotFoundException时提供FileName。

使用.Net内置异常

  • 不要使用System.Exception,而要使用它的子类。
    InvalidOperationExceptionArgumentException

自定义异常

  • 名字以Exception结尾。

  • 使异常可序列化,并将异常定义放在公共程序集中。以使异常在远程调用或跨应用域时可用。

  • 定义三个构造函数。

[Serializable]
public class ExampleException: Exception
{
    public ExampleException()
    {
    }

    public ExampleException(string message)
        : base(message)
    {
    }

    public ExampleException(string message, Exception inner)
        : base(message, inner)
    {
    }
}

实践

GUI

对于使用Application.ThreadException捕获所有

使用帮助类

// throw NewFileIOException();

FileReaderException NewFileIOException()
{
    string description = "My NewFileIOException Description";
    return new FileReaderException(description);
}

三种模式

Try-Parse 模式

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

使用Try前缀及返回bool变量。
同时提供会抛出异常(不带Try)的方法。

Tester-Doer 模式

if (conn.State != ConnectionState.Closed)
{
    conn.Close();
}

当异常经常发生或本身为正常流程的一部分时,推荐此种模式。

Try-Catch 模式

try
{
    conn.Close();
}
catch (InvalidOperationException ex)
{
    Console.WriteLine(ex.GetType().FullName);
    Console.WriteLine(ex.Message);
}

当异常很少发生时(即异常是一个预期外错误),使用此模式可以减少正常执行时多余的判断步骤。

参考

Design Guidelines for Exceptions

Handling and throwing exceptions in .NET