C# 使用异常的更好方法是什么?

C# 使用异常的更好方法是什么?,c#,exception,C#,Exception,我有两种创建异常的方法 public class Class1 { public void Method1() { try { Method1ThrowException(); } catch (Exception e) { Console.WriteLine(e); } } public void Method1Thr

我有两种创建异常的方法

public class Class1
{
    public void Method1()
    {
        try
        {
            Method1ThrowException();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    public void Method1ThrowException()
    {
        throw new Exception();
    }
}
public class Class2
{
    public void Method2()
    {
        try
        {
            Method2ThrowException();
        }
        catch (MethodException e)
        {
            Console.WriteLine(e);
        }
    }

    public void Method2ThrowException()
    {
        throw new MethodException();
    }
}

public class MethodException : Exception
{
    public MethodException()
    {

    }

    public MethodException(string message) : base(message)
    {

    }

    public MethodException(string message, Exception inner) : base(message, inner)
    {

    }
}
第一种方法:我使用基本异常类创建异常

public class Class1
{
    public void Method1()
    {
        try
        {
            Method1ThrowException();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    public void Method1ThrowException()
    {
        throw new Exception();
    }
}
public class Class2
{
    public void Method2()
    {
        try
        {
            Method2ThrowException();
        }
        catch (MethodException e)
        {
            Console.WriteLine(e);
        }
    }

    public void Method2ThrowException()
    {
        throw new MethodException();
    }
}

public class MethodException : Exception
{
    public MethodException()
    {

    }

    public MethodException(string message) : base(message)
    {

    }

    public MethodException(string message, Exception inner) : base(message, inner)
    {

    }
}
第二种方法:用这种方法创建用户定义的异常类,然后使用该类创建异常

public class Class1
{
    public void Method1()
    {
        try
        {
            Method1ThrowException();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    public void Method1ThrowException()
    {
        throw new Exception();
    }
}
public class Class2
{
    public void Method2()
    {
        try
        {
            Method2ThrowException();
        }
        catch (MethodException e)
        {
            Console.WriteLine(e);
        }
    }

    public void Method2ThrowException()
    {
        throw new MethodException();
    }
}

public class MethodException : Exception
{
    public MethodException()
    {

    }

    public MethodException(string message) : base(message)
    {

    }

    public MethodException(string message, Exception inner) : base(message, inner)
    {

    }
}
使用异常的这种方式有什么区别


我读到使用第二种方法更好,我不明白为什么?在这两种方法中,我都只是创建异常并获取它们。

第二种方法更好,因为您可以创建适合特定情况的自己的异常类型。例如:您可以在编写通过某个网络进行通信的应用程序时创建ConnectionBrokenException类型,并在连接断开时抛出它

这为您提供了两个主要优势:

首先
根据异常类型的不同,可以使用try..catch块以不同的方式处理异常。您可以决定向用户显示消息、回滚某些操作或执行其他操作

try
{
    ... code throwing ConnectionBrokenException
}
catch(ConnectionBrokenException ex)
{
    _logger.LogError("Something bad has happened with connection", ex.Message);
}
catch(Exception)
{
    // handles other types of exceptions
}


在分析来自此类应用程序的日志时,如果每个坏情况都有自己的异常,则更容易诊断一些问题。例如,您可以使用一些筛选来查找您感兴趣的唯一异常。

第二种方法更好,因为您可以创建适合特定情况的自己的异常类型。例如:您可以在编写通过某个网络进行通信的应用程序时创建ConnectionBrokenException类型,并在连接断开时抛出它

这为您提供了两个主要优势:

首先
根据异常类型的不同,可以使用try..catch块以不同的方式处理异常。您可以决定向用户显示消息、回滚某些操作或执行其他操作

try
{
    ... code throwing ConnectionBrokenException
}
catch(ConnectionBrokenException ex)
{
    _logger.LogError("Something bad has happened with connection", ex.Message);
}
catch(Exception)
{
    // handles other types of exceptions
}

在分析来自此类应用程序的日志时,如果每个坏情况都有自己的异常,则更容易诊断一些问题。例如,您可以使用一些筛选来查找您感兴趣的唯一异常。

因为
捕获(异常e)
捕获所有内容。没有办法区分提出了什么样的例外情况。因此,细粒度错误类是好的

(还有,为什么要定义
Method1ThrowException
,而不是在需要抛出异常的地方抛出异常呢?这只会给堆栈跟踪添加一个无用的层。)

因为
捕获(异常e)
捕获所有内容。没有办法区分提出了什么样的例外情况。因此,细粒度错误类是好的


(还有,为什么要定义
Method1ThrowException
,而不是在需要抛出异常的地方抛出异常呢?这只会给堆栈跟踪添加一个无用的层。)

没有更好的方法,因为它取决于您的具体需要

如果存在可以使用的现有异常类型,只需使用该异常类型(
ArgumentException
etc)。请参阅以获取列表

如果需要特殊的异常类型,请创建自己的异常类型,其中包含自己的自定义属性。例如:

 public BusinessException : Exception
 {
     public BusinessException(string reason)
     {
           Reason  = reason;
     }
     public string Reason {get; set;}
 }

如果要在WCF服务中抛出这些异常,请确保添加全局异常处理程序以将这些异常映射到WCF故障。如果是web API,请将它们映射到HTML状态。

没有更好的方法,因为这取决于您的具体需求

如果存在可以使用的现有异常类型,只需使用该异常类型(
ArgumentException
etc)。请参阅以获取列表

如果需要特殊的异常类型,请创建自己的异常类型,其中包含自己的自定义属性。例如:

 public BusinessException : Exception
 {
     public BusinessException(string reason)
     {
           Reason  = reason;
     }
     public string Reason {get; set;}
 }

如果要在WCF服务中抛出这些异常,请确保添加全局异常处理程序以将这些异常映射到WCF故障。对于web API,请将它们映射到HTML状态。

“更好”主要基于观点。两者都将执行相同的操作,通过调用堆栈冒泡一个异常。一个由BCL提供,一个由您定制。当您创建第三方库并希望创建引用库代码的异常时,您可能会发现这一点很有用,方法是将它们包装在
my傻瓜库异常
中。创建自己的异常类型很有用,除非BCL类型更合适。记住@YuvalItzchakov:不是真正基于意见的。假设你去一家餐馆,你会看到“食物:$10”。你点牛排;他们说:“对不起,我们只有食物。你想要一些吗?”我说,我宁愿去一家菜单上写着他们供应什么的餐馆;我敢打赌大多数人都会同意我的观点。@Amadan我很高兴你饿了,但我认为这个问题更像是BCL例外而不是自定义例外。我不认为OP真正的意思是“只使用常规
异常
类型”。在我看来,他好像在问“创建自定义异常是否更好”。代码分析将对第一个代码段发出警告CA2201。因此,您可以定义并抛出自己的异常,或者根据需要使用现有异常,如InvalidOperationException。见“更好”主要是基于意见。两者都将执行相同的操作,通过调用堆栈冒泡一个异常。一个由BCL提供,一个由您定制。当您创建第三方库并希望创建引用库代码的异常时,您可能会发现这一点很有用,方法是将它们包装在
my傻瓜库异常
中。创建自己的异常类型很有用,除非BCL类型更合适。记住@YuvalItzchakov:不是真正基于意见的。假设你去一家餐馆,你会看到“食物:$10”。你点牛排;他们说:“对不起,我们只有食物。你想要一些吗?”我说,我宁愿去一家菜单上写着他们供应什么的餐馆;我敢打赌大多数人都会同意我的观点。@Amadan我很高兴你饿了,但我认为这个问题更像是BCL例外而不是自定义例外。我不认为OP真正的意思是“只使用常规
异常
类型”。在我看来,他好像在问“创建自定义异常是否更好”。代码分析将对第一个代码段发出警告CA2201。