C# 为什么在main()中的try catch不好?

C# 为什么在main()中的try catch不好?,c#,exception,C#,Exception,有人能解释一下为什么在main()方法中使用try-catch来捕获任何未处理的异常是不合适的吗 [STAThread] static void Main() { try { Application.Run(new Form1()); } catch (Exception e) { MessageBox.Show("General error: " + e.ToString()); } } 我知道这是一种不好的做

有人能解释一下为什么在main()方法中使用try-catch来捕获任何未处理的异常是不合适的吗

[STAThread]
static void Main()
{
    try
    {
        Application.Run(new Form1());
    }
    catch (Exception e)
    {
         MessageBox.Show("General error: " + e.ToString());
    }
}

我知道这是一种不好的做法,但不知道为什么。

这里有一个“一网打尽”的例外,它将捕获所有内容。因此,如果代码中有任何未处理的异常,您将永远看不到它们

从积极的方面来看,您的应用程序永远不会崩溃


如果这是必需的行为,那么您需要有足够的日志记录和报告,以便让用户和您(作为开发人员)都知道发生了什么,并尽可能优雅地恢复或退出。

我不认为这是一种不好的做法

让程序因未经处理的异常错误而崩溃不会给最终用户带来任何信心

也许其他人可以提供相反的观点

更新: 显然,你需要做一些有用的例外

  • 记录下来
  • 向用户显示一个对话框,说明应用程序退出的原因(纯文本,而不是stacktrace)
  • 在应用程序上下文中有意义的其他内容

  • 我认为这本身并不是一个坏习惯。我认为,如果这是应用程序中唯一的try/catch块,那么糟糕的做法可能是。

    我认为这不一定是糟糕的做法。然而,有一些警告

    我相信,无论谁称这为“糟糕的做法”,都是为了强化这样一种观点,即您应该捕获最接近异常发生位置的异常(即尽可能高/适当)。总体异常处理程序通常不是一个好主意,因为它大大减少了可用的控制流。粗粒度异常处理非常重要,它不是程序稳定性的合理解决方案。不幸的是,许多初学者都认为是这样,并采取了这种方法,如下面的try-catch语句

    这样说来,如果您在程序的其余部分正确地使用了异常处理(以细粒度和特定于任务的方式),并相应地处理了错误(而不是显示一个通用错误框),那么在
    Main
    方法中对所有异常进行常规的try-catch可能是一件有用的事情。这里需要注意的一点是,如果您在这个
    Main
    try-catch中重复捕获bug,那么您要么有bug,要么本地异常处理有问题


    此try-catch with
    Main
    的主要用途纯粹是为了防止您的程序在非常不寻常的情况下崩溃,它应该只向用户显示一条(模糊的)用户友好的“致命错误”消息,以及可能在某处记录错误和/或提交错误报告。因此,总结一下:这种方法确实有它的用途,但必须非常小心,不要出于错误的原因。

    我不确定我是否认为这是一种不好的做法。您要做的是确保程序崩溃时的异常和当前状态最终掌握在开发人员手中,最好记录日期、时间和使用它的用户。基本上-您希望确保您的团队拥有调试问题所需的所有信息,而不管用户是否向他们询问崩溃情况。请记住,事实上,许多用户在遇到崩溃时不会联系支持人员


    这里的错误做法是捕获异常,显示一个简单的“错误”对话框,然后关闭应用程序。在这种情况下,该异常的状态将永远丢失。

    好的,该方法将只捕获主线程中抛出的异常。如果同时使用和事件,则可以捕获并记录所有异常。

    从调试的角度来看,这可能会使操作更加困难,因为它会使每个异常都成为用户处理的异常。这会更改调试器的行为,除非您中断未处理的异常,否则可能会出现其他问题

    尽管如此,我认为在发布时这是一个很好的实践。此外,我还建议您听一下新闻和事件。这将允许您捕获更多的异常(例如,上面的“全局”处理程序中不会捕获的一些系统异常)


    这允许您记录错误并向用户提供一条好的、干净的消息。

    我并不是说这是一种不好的做法,但我唯一要做的不同是使用内置事件:

            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
    
            static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
            {
                MessageBox.Show(e.Exception.Message); //or do whatever...
            }
    

    换成这个就好了

    catch(Exception ex)
    {
        YourLoggingSystem.LogException(ex);
    }
    

    当然,这一行永远不应该出现,因为在整个代码中,您将有其他异常处理程序使用更多的上下文来捕获内容。

    顶级异常处理非常重要,但我建议使用:

    Application.ThreadException += new ThreadExceptionEventHandler(YourExceptionHandlingMethod); 
    
    但是,这只会捕获GUI线程上的异常(很像try..catch块)——您应该为每个新线程使用类似的代码来处理来自它们的任何意外异常


    更多信息。

    任何进入
    Main()
    的异常都可能是致命的

    如果这是件容易的事,就应该由上级来处理。如果它超出了您的控制范围,例如
    OutOfMemoryException
    ,那么程序应该崩溃


    崩溃的Windows应用程序有一种标准的方法,它们会触发对话框。(你可能以前见过它)。当发生这种情况时,你可以注册接收崩溃数据。在古时候,

    < P>,在C++中放置一个尝试/捕获会导致相当严重的性能损失,并且在主周围放置一个将意味着为所有的东西存储额外的堆栈信息,这对性能来说是不好的。 现在计算机速度更快了,程序员对性能的依赖性降低了,运行时的构建也更好了,所以它不再那么糟糕了(但你可能会为此付出更多,因为多年来都没有对它的效果进行基准测试)。所以是老福尔克