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

发布于 2024-08-11 04:16:47 字数 804 浏览 4 评论 0原文

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

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

尽管我认为它的可读性比以前的版本要差得多。

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

I have a section of code that looks like this:

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

  classVar = functionCall(input, sEnum.Second);

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

However my exception dosent show which specific call it came from. The stack trace also only shows details from another class called from inside the function call.

The alternative way to wrap this is:

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

Though I think it is much less readable that the previous version.

Is there a pattern for wrapping the function calls or passing off the exceptions in such a way that i can later see where they came from while keeping the code readable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

水溶 2024-08-18 04:16:47

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

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

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

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

What you probably want to do is capture and show the exception stack trace in addition to just the string value of the exception.

You can do this by using the StackTrace property on the exception. This will let you see where the exception happened.

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

Sample of how to get it to print. I'm sure you can figure out how to integrate it in with your debug system.

梦幻的味道 2024-08-18 04:16:47

在 functioncall() 方法中添加 try/catch 并在其中添加 debug.assert 。如果确实需要,您可以在那里重新抛出异常,将其沿着链向上传递到这段代码。

Add a try/catch inside the functioncall() method and debug.assert there as well. If you absolutely need to, you can re-throw the exception there to pass it up the chain to this bit of code.

怪我太投入 2024-08-18 04:16:47

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

The line number in the stack trace will tell you which of the three were called.

世俗缘 2024-08-18 04:16:47

选项 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"
);

Option 1
Change functionCall() to re-throw a custom exception with contextual information. Catch the exception at a higher level for logging, calling Debug.Assert, etc.

Option 2
This pattern can provide reuse of exception handling logic at a slight loss in readability. Caution: over-use of delegate techniques at the cost of clarity can become a code smell.

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"
);
绅士风度i 2024-08-18 04:16:47

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

How about writing your own exception class that carries as part of its payload the enum value? You can also write the log message to be more descriptive so that you don't have to rely on the stack trace to be the sole source of information.

北笙凉宸 2024-08-18 04:16:47

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

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

While it may not be the most elegant solution, you can add another variable to keep track of what step you are on:

    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());
   }
御守 2024-08-18 04:16:47

这有点天真,但是......

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 :)

This is a little naive but...

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 is basically an state machine that hold the actual state you're performing. You can define it as a base class an inherit from it for specific cases ...

Edited to make it more .NET like :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文