仅在 Release 中尝试捕获的更好方法?

Posted

技术标签:

【中文标题】仅在 Release 中尝试捕获的更好方法?【英文标题】:Better way for try-catch only in Release? 【发布时间】:2017-04-26 03:13:15 【问题描述】:

当我想调试抛出异常的应用程序时,这意味着我需要像这样禁用 try-catch 块:

#if !DEBUG
                try
                
#endif
                    // Do something
#if !DEBUG
                
                catch (ArgumentException)
                
                    Console.WriteLine("Something wrong");
                
#endif

注意:我知道 Visual Studio 处理异常时会中断,但缺点是它会在同一类型的每个异常处中断。 编辑改写我的意思:例如,函数 A 和 B 都抛出 NullReferenceException,但我只想检查 A 何时抛出它,而不是 B(在 B 中处理的 NulRefExc 已经正确)。 p>

有人可能会问我为什么需要它。通常我在没有调试的情况下运行 ASP.NET MVC 代码(但仍在调试构建中,它具有 DEBUG 变量),并且抛出异常而不是捕获它真的很棒(当然仅在开发模式下),因为带有堆栈跟踪的错误页面将显示出来,因此我们可以更快地跟踪错误。

上面的代码有没有更简洁的写法?

【问题讨论】:

我不明白这样做(想象有一种方法)如何使您免于“缺点是它会在同一类型的每个异常时中断,无论它发生在哪里” 你需要捕获全局异常吗?并在其上设置断点,您将在调试器中获得带有堆栈跟踪的完整异常。 谷歌asp mvc global error handler @user5328504 抱歉,我改写了我的意思。 【参考方案1】:

从 C# 6 开始,您也可以使用 exception filters:

try

    // Do something

catch (ArgumentException) when (!Env.Debugging)

    // Handle the exception

Env.Debugging 定义为某处

public static class Env

#if DEBUG
    public static readonly bool Debugging = true;
#else
    public static readonly bool Debugging = false;
#endif

作为额外的奖励,当异常对象未被捕获时,您将在异常对象中获得原始调用堆栈(由于when 测试失败,即在调试中)。对于重新抛出的异常,您必须提供原始异常作为内部异常,并付出一些额外的努力来处理它。

此方法还允许根据其他条件启用/禁用异常处理,例如 web.config 设置,这将允许您在不重新编译的情况下切换:

public static class Env

    public static readonly bool Debugging =
      Convert.ToBoolean(WebConfigurationManager.AppSettings["Debugging"]);

【讨论】:

酷!我从来没有想过这个。现在这个问题有 2 个很好的答案,我不知道要标记哪个。 P.s:public const bool 是一个较短的版本。 对于 .NET Core,您可以使用:catch (Exception ex) when (!_hostingEnvironment.IsDevelopment()) 并在构造函数中注入 IHostingEnvironment【参考方案2】:

只是一个想法 离开try catch

然后做

 catch (ArgumentException)
                
#if DEBUG
                throw SomeCustomExceptionYouCatchWith_break_on_handled_exception();
#endif
                    Console.WriteLine("Something wrong");
                

【讨论】:

你甚至可以让自定义异常获取原始异常作为构造函数参数 哇,这太棒了!正是我需要的!如果只是一个简单的调试代码,#if 指令之间的throw; 语句就足够了:) @DatVM 在生产中不会写入Console,而是将其写入日志。 Where does console writeline go in asp @CodingYoshi 是的,抱歉上面的代码只是我的例子,我知道 Console.WriteLine (几乎)什么都不做。我的问题主要目标是在开发环境中,堆栈跟踪是我们最关心的问题(但我们仍然有用于生产的 try-catch)【参考方案3】:

两件事:

    #if DEBUG 你要去多少个地方? Console.WriteLine 在 ASP.NET 中毫无意义。请参阅this 了解更多信息。

您应该做的是将错误记录到数据库、文件或其他内容中。这将避免代码中的所有#if DEBUGs。有关日志记录的更多信息,请参阅this。

这有额外的好处:

    您将能够看到您的错误是什么样的,因此当您投入生产时,您将获得相同的信息。如果您没有足够的信息,在日志中,在开发过程中,它让您有机会更改错误消息并确保堆栈跟踪存在。这在您投入生产时会很有帮助,因为现在您有更好的错误。 您的代码更简洁

【讨论】:

我确实认为你应该在未来的某个地方遵循这个建议。你目前的方法会变得丑陋 @user5328504 对不起,你是什么意思? 我的意思是你应该(在未来)制定一个更好的日志记录机制。现在不用担心,下次告诉自己如何处理跟踪和日志记录。不过,现在不要为此失眠 我不确定你是在告诉我那个还是 OP 但好吧我还是会去睡觉 我也不会。我也不会

以上是关于仅在 Release 中尝试捕获的更好方法?的主要内容,如果未能解决你的问题,请参考以下文章

UIButton - 仅在没有待处理事件时调用 Release?

未捕获的错误:Tabledit 仅在应用于表时有效

有没有更好的方法从 Vuetify 组件中捕获错误?

c# Naudio 音频电平捕获和显示,仅在打开录音属性时有效

cudaGraph:多线程流捕获仅在 cuda-memcheck 中运行时才会导致错误

仅在“RELEASE”构建模式中命名为异常的多个 JSON 字段