1

我有一段代码如下所示:

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

虽然我认为它的可读性比以前的版本要低得多。

是否有包装函数调用或传递异常的模式,以便我以后可以在保持代码可读性的同时看到它们的来源?

4

7 回答 7

4

除了异常的字符串值之外,您可能想要做的是捕获并显示异常堆栈跟踪。

您可以通过对异常使用 StackTrace 属性来执行此操作。这将使您看到异常发生的位置。

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

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

于 2009-11-12T16:13:59.310 回答
2

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

于 2009-11-12T16:12:15.163 回答
2

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

于 2009-11-12T16:12:55.710 回答
1

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

于 2009-11-12T16:12:58.890 回答
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"
);
于 2009-11-12T19:37:10.413 回答
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());
   }
于 2009-11-12T16:16:03.487 回答
-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 :)

于 2009-11-12T16:15:10.370 回答