从代码部分捕获异常的模式(同时不会让眼睛流血)

时间:2009-11-12 16:09:52

标签: .net exception-handling c#-3.0 code-readability

我有一段看起来像这样的代码:

try
{
  classVar = functionCall(input, sEnum.First);

  classVar = functionCall(input, sEnum.Second);

  classVar = functionCall(input, sEnum.Third);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}

然而,我的异常剂量显示它来自哪个特定的电话。堆栈跟踪也只显示来自函数调用内部调用的另一个类的详细信息。

包装它的另一种方法是:

try
{
  classVar = functionCall(input, sEnum.First);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}
try
{
  classVar = functionCall(input, sEnum.Second);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}
try
{
  classVar = functionCall(input, sEnum.Thrid);
}
catch (Exception ex)
{
  Debug.Assert(false, ex.ToString());
}

虽然我认为它的可读性远低于以前的版本。

是否有一种模式用于包装函数调用或以某种方式传递异常,以便稍后可以看到它们来自哪里,同时保持代码可读?

7 个答案:

答案 0 :(得分:4)

您可能想要做的是捕获并显示异常堆栈跟踪以及异常的字符串值。

您可以通过在异常上使用StackTrace属性来完成此操作。这将让您看到发生异常的位置。

catch (Exception e) { 
    Console.WriteLine(e.StackTrace);
}

如何打印它的示例。我相信你可以弄清楚如何将它与调试系统集成。

答案 1 :(得分:2)

在functioncall()方法和debug.assert中添加try / catch。如果你绝对需要,可以在那里重新抛出异常,将链传递给这段代码。

答案 2 :(得分:2)

堆栈跟踪中的行号将告诉您三个中的哪一个被调用。

答案 3 :(得分:1)

如何编写自己的异常类,作为其有效负载的一部分携带枚举值?您还可以编写日志消息以使其更具描述性,这样您就不必依赖堆栈跟踪作为唯一的信息来源。

答案 4 :(得分:1)

选项1 更改functionCall()以使用上下文信息重新抛出自定义异常。在更高级别捕获异常以进行日志记录,调用Debug.Assert

选项2 这种模式可以在可读性略有损失的情况下提供异常处理逻辑的重用。注意:以清晰为代价过度使用委托技术可能会成为代码味道。

static void InvokeActionWithContext(Action action, string description) {
   try 
   {
     action();
   }
   catch(Exception ex)
   {
     throw new AnExceptionWithContext(description, ex);
   }
}

// call like this
InvokeActionWithContext( 
   () => classVar = functionCall(input, sEnum.Third),
   "Initializing value three"
);

答案 5 :(得分:0)

虽然它可能不是最优雅的解决方案,但您可以添加另一个变量来跟踪您所处的步骤:

    int step = 0;
    try
    {
       classVar = functionCall(input, sEnum.First);
       step++;

      classVar = functionCall(input, sEnum.Second);
      step++;

      classVar = functionCall(input, sEnum.Third);
   }
   catch (Exception ex)
   {
      //examine the step variable here

      Debug.Assert(false, ex.ToString());
   }

答案 6 :(得分:-1)

这有点幼稚,但......

ExceptHandler<sEnum> h = new ExceptHandler<sEnum>();
try
{
  h.Step = sEnum.First;
  classVar = functionCall(input, sEnum.First);
  h.Step = sEnum.Second;
  classVar = functionCall(input, sEnum.Second);
  h.Step = sEnum.Third;
  classVar = functionCall(input, sEnum.Third);
}
catch (Exception ex)
{
  h.AssertException(ex.ToString());
}

ExceptHandler基本上是一个状态机,可以保存您正在执行的实际状态。您可以将其定义为基类,并从特定情况继承它...

编辑使其更像.NET:)