如何处理异常

问题描述 投票:2回答:13

我的技术负责人坚持采用这种异常机制:

try
{
    DoSth();
}
catch (OurException)
{
    throw;
}
catch (Exception ex)
{
    Util.Log(ex.Message, "1242"); // 1242 is unique to this catch block
    throw new OurException(ex);
}

1242这里是catch方法的标识符,我们可以处理OurOur以外的异常。项目中的每个catch块都必须具有唯一的标识符,以便我们可以通过查看日志来了解异常发生的位置。

对于每个方法,我们都必须捕获OurException并将其抛出。如果引发了其他类型的异常,我们必须先记录下来并用OurException对其进行屏蔽,然后再将其抛出。

这是一种合理的方法吗?如果有的话,还有什么更好的选择?

Edit:我被告知堆栈跟踪在发布模式下不会产生有意义的结果。您是否建议捕获并抛出通用异常是可以的?

Edit2:谢谢大家。我将您的答案用作反对该论点的一部分,但有人告诉我您经验不足,也不知道如何应对现实生活中的情况。我必须走这条路。

language-agnostic exception exception-handling
13个回答
5
投票

您也可以查看Exception Handling Application block.

我已经在一些项目中使用它,它非常有用。特别是如果您以后想要更改异常处理的工作方式以及要捕获的信息。


0
投票

缺点:

  1. 这个数字不会激发太大的信心,堆栈跟踪会更好一些

  2. 如果您的自定义异常可以在“ catch(ex exException)中处理,为什么要有2个catch块“?


0
投票

我认为这是一个错误的模式,因为您可以获得有关异常中整个调用堆栈的信息,因此无需通过记录并重新抛出异常来伪处理该异常。仅在确实可以解决问题的地方捕获异常。


0
投票

记录堆栈跟踪信息将比硬编码数字好得多。该数字告诉您什么例程称为此例程。

同样,数字管理起来很麻烦,并且容易出错。

edit:的确,stacktrace不会always在发布模式下产生有意义的结果,但是我认为对于这种硬编码数字方案也可以这么说! :-)

使用您使用的语言,编译器是否为宏提供当前文件名和行号?这比尝试自己输入一个唯一号码要好。而且,如果您不能自动执行此操作,请手动执行此操作,或者想出一些方案来确保唯一性,而不需要对数字进行集中分配!


0
投票

我的应用程序是在发布模式下构建的,并且我使用异常处理应用程序块,所以我从来没有任何catch ex代码块,它被EHAB捕获,它本身将包含所有信息的日志文件写入日志文件。需要;堆栈跟踪等,时间等。

唯一的问题是有人放了

catch ex
{
    //do stuff
    throw ex;
}

因为这将清除堆栈跟踪。


3
投票

我认为使用堆栈跟踪将比任何标识符都直观得多。

关于自定义例外,为什么不这样做?

try
{
DoSth();
}
catch(Exception ex)
{
Util.Log(ex.Message, ex.StackTrace);
if(ex is OurException) throw ex;
else throw new OurException(ex); // use the original exception as the InnerException
}

此外,我不确定为什么要在处理异常后重新抛出该异常-您能解释其背后的原因吗?

@@ Ali A-一个非常有效的观点,所以请允许我重新措辞-为什么要重新抛出异常而不是在此处立即完成处理?

编辑:

而不是抛出,为什么不这样做?

try
{
DoSth();
}
catch(Exception ex)
{
Util.HandleException(ex);
}

Util.HandleException:

public static void HandleException(ex)
{
Util.Log(ex); // Util.Log should log the message and stack trace of the passed exception as well as any InnerExceptions - remember, than can be several nested InnerExceptions.

// Any additional handling logic, such as exiting the application, or showing the user an error message (or redirecting in a web app)
}

这样,您知道每个异常只会被记录一次,并且不会将它们扔回野外以造成任何其他破坏。


2
投票

具有OurException有点奇怪。通常,您希望有专门的捕获块,然后是最后一个,即捕获通用Exception的块,您可以在其中进行日志记录:

try 
{
    DoSomething();
}
catch (DivideByZeroException)
{
    // handle it here, maybe rethrow it, whatever
}
// more catch blocks
catch (Exception)
{
    // oops, this is unexpected, so lets log it
}

但是您的所作所为将起作用。我确实相信1242应该会。这是一种打印方法,文件名和行号的方法。我自己还没有尝试过,但是看起来不错:

    [Conditional("DEBUG")]
    public static void DebugPrintTrace()
    {
        StackTrace st = new StackTrace(true);
        StackFrame sf = st.GetFrame(1); // this gets the caller's frame, not this one
        Console.WriteLine("Trace "
            + sf.GetMethod().Name + " "
            + sf.GetFileName() + ":"
            + sf.GetFileLineNumber() + "\n");
    } 

1
投票

我有两种类型的异常:可修复异常和致命异常。如果某个对象抛出可修复的异常,则表示发生了错误,但对象没有损坏,可以再次使用。如果某个对象抛出致命异常,则意味着对象状态已损坏,任何使用该对象的尝试都会导致新的错误。

Update:所有异常可能会尽快处理,并尽可能接近错误源。例如,如果存储在集合中的对象引发致命异常,则异常处理程序仅从集合中删除该对象并删除它,而不是所有对象的整个集合。


1
投票

据我了解,异常的目的是传播意外错误。如果您将其捕获到与抛出它的方法足够接近的位置,那么您将更多地了解如何处理它。

您的示例是捕获意外错误,然后将其重新抛出。这不是在处理异常,而是将其包装到您自己的异常中。

但是您的包裹似乎并没有为异常增加更多的价值,但是甚至可能使事情变得混乱。

一个极端的例子:

void a() {
  try {
    c();
  } catch(MyException1 ex) {
    throw;
  } catch(Exception ex) {
    log(ex);
    throw new MyException1(ex);
  }
}

void b() {
  try {
    a();
  } catch(MyException2 ex) {
    throw;
  } catch(Exception ex) {
    log(ex);
    throw new MyException2(ex);
  }
}

请注意,在前面的示例中,原始异常记录了两次。它包含两个例外。当您多次记录同一异常时,将很难跟踪(因为日志文件变得很大)。

当然,这可能是一个极端的例子,但是我很难相信您的整个应用程序仅使用一种类型的异常。它没有充分描述可能发生的所有不同类型的错误。

我个人更喜欢仅将异常记录在处理异常的catch块中。其他任何地方都可能会创建重复的日志记录。


0
投票

我认为在抛出行上使用硬编码的号码不是一个好习惯,您如何知道该号码是否正在使用?或者,下一个要抛出的错误号码是?也许您至少可以在一个枚举上列出...不确定。


0
投票

除了那个怪异的数字,一切看起来都不错。

堆栈跟踪将包含您需要的信息。


0
投票

在我看来,stacktrace是处理此问题的更好方法。如果您错误地重复使用数字会怎样?

至于这是否是个好主意,在没有更多信息的情况下,我倾向于拒绝。如果每个方法调用都包装在try / catch块中,则将非常昂贵。通常,异常分为两个阵营:可以合理预期和处理的异常,以及确实是错误(或至少未成功预期)的异常。在我看来,使用a弹枪方法捕获所有异常似乎是隐藏后者可能比帮助解决这些问题做更多的事情。如果在顶层捕获了所有异常,因此唯一的记录是日志消息,则尤其如此。


0
投票

我看不出这有什么帮助。您已经知道堆栈跟踪来自何处,并且正在添加不必要的复杂程度。

© www.soinside.com 2019 - 2024. All rights reserved.