C# 程序检查或尝试…捕获

C# 程序检查或尝试…捕获,c#,exception-handling,C#,Exception Handling,我这里有一些代码: public static void OpenConnection(IDbConnection connection) { if(connection == null) throw new ArgumentNullException("connection", "The connection was null."); if (connection.State != ConnectionState.Closed) connect

我这里有一些代码:

public static void OpenConnection(IDbConnection connection)
{
    if(connection == null)
        throw new ArgumentNullException("connection", "The connection was null.");

    if (connection.State != ConnectionState.Closed)
        connection.Close();
}
由于每次在数据库中执行某项操作时都会打开和关闭连接,因此必须执行大量代码。我想知道下一个代码是否是性能方面更好的解决方案:

public static void OpenConnection(IDbConnection connection)
{
    try
    {
        connection.Close();
    }
    catch (NullReferenceException nullReferenceException) { throw; }
    catch (Exception exception) { } // This will occur if the connection was already closed so nothing should be done then.
}
PS.是否需要捕获异常{}


编辑:在第二段代码中,将ArgumentNullException替换为NullReferenceException,因为当连接==null时,会出现异常。

根据Microsoft的说法,异常会对性能造成巨大的影响。在合理的情况下尽量避免:

抛出异常可能非常昂贵,因此请确保不要抛出太多异常。使用Perfmon查看应用程序引发的异常数量。您可能会惊讶地发现,应用程序的某些区域抛出的异常比您预期的要多。为了获得更好的粒度,还可以使用性能计数器以编程方式检查异常数

查找和设计异常严重的代码可以获得良好的性能。请记住,这与try/catch块无关:只有在抛出实际异常时才会产生成本。您可以使用任意数量的try/catch块。无偿使用异常会导致性能下降。例如,您应该避免使用异常作为控制流

您的第二个示例实际上是一个更糟糕的场景。你几乎不应该抓住一般的例外情况。您可能认为您知道将抛出什么,但很可能会抛出意外的内容,从而导致系统不稳定和可能的数据丢失/损坏

使用Catch异常e仍然是错误的

即使CLR异常系统将最坏的异常标记为CSE,在代码中编写catch异常仍然不是一个好主意。例外情况代表了一系列意想不到的情况。CLR可以检测最坏的异常SEH异常,这些异常指示可能已损坏的进程状态。但是,如果忽视或笼统处理其他意外情况,它们仍然可能是有害的

在没有进程损坏的情况下,CLR为程序正确性和内存安全提供了一些非常有力的保证。当执行用安全的Microsoft中间语言MSIL代码编写的程序时,可以确保程序中的所有指令都将正确执行。但是,按照程序指令所说的去做,往往不同于按照程序员的意愿去做。根据CLR完全正确的程序可能损坏持久状态,例如写入磁盘的程序文件


根据微软的说法,异常是对性能的巨大打击。在合理的情况下尽量避免:

抛出异常可能非常昂贵,因此请确保不要抛出太多异常。使用Perfmon查看应用程序引发的异常数量。您可能会惊讶地发现,应用程序的某些区域抛出的异常比您预期的要多。为了获得更好的粒度,还可以使用性能计数器以编程方式检查异常数

查找和设计异常严重的代码可以获得良好的性能。请记住,这与try/catch块无关:只有在抛出实际异常时才会产生成本。您可以使用任意数量的try/catch块。无偿使用异常会导致性能下降。例如,您应该避免使用异常作为控制流

您的第二个示例实际上是一个更糟糕的场景。你几乎不应该抓住一般的例外情况。您可能认为您知道将抛出什么,但很可能会抛出意外的内容,从而导致系统不稳定和可能的数据丢失/损坏

使用Catch异常e仍然是错误的

即使CLR异常系统将最坏的异常标记为CSE,在代码中编写catch异常仍然不是一个好主意。例外情况代表了一系列意想不到的情况。CLR可以检测最坏的异常SEH异常,这些异常指示可能已损坏的进程状态。但是,如果忽视或笼统处理其他意外情况,它们仍然可能是有害的

在没有进程损坏的情况下,CLR为程序正确性和内存安全提供了一些非常有力的保证。当执行用安全的Microsoft中间语言MSIL代码编写的程序时,可以确保程序中的所有指令都将正确执行。但是,按照程序指令所说的去做,往往不同于按照程序员的意愿去做。根据CLR完全正确的程序可能损坏持久状态,例如写入磁盘的程序文件

我想知道下一个代码在性能方面是否是一个更好的解决方案

考虑性能和功能方面的问题 不同之处在于:

连接为空 您将获得一个NullReferenceException,而不是ArgumentNullException,这是一个功能上的区别,因为您获得了不同的异常类型和较少的关于异常发生原因/位置的上下文。如果您决定捕获NullReferenceNexception并抛出ArgumentNullException,那么您将有抛出新异常的开销,因此会影响性能

连接未关闭。 尝试关闭连接-此处没有实际性能或功能差异

连接已关闭 您尝试再次关闭连接。这可能不是一个巨大的功能差异,因为如果您试图关闭一个已经关闭的连接,大多数提供者可能不会生气,但这是不必要的,并且可能会有一些性能缺点,这取决于close方法的实际功能

因此,您的第二种方法在功能上存在差异,实际上可能在性能方面存在缺点

坚持更清晰地说明预期行为的代码——只有在存在可测量、可纠正的性能问题时才进行优化

我想知道下一个代码在性能方面是否是一个更好的解决方案

考虑每种情况下的性能和功能差异:

连接为空 您将获得一个NullReferenceException,而不是ArgumentNullException,这是一个功能上的区别,因为您获得了不同的异常类型和较少的关于异常发生原因/位置的上下文。如果您决定捕获NullReferenceNexception并抛出ArgumentNullException,那么您将有抛出新异常的开销,因此会影响性能

连接未关闭。 尝试关闭连接-此处没有实际性能或功能差异

连接已关闭 您尝试再次关闭连接。这可能不是一个巨大的功能差异,因为如果您试图关闭一个已经关闭的连接,大多数提供者可能不会生气,但这是不必要的,并且可能会有一些性能缺点,这取决于close方法的实际功能

因此,您的第二种方法在功能上存在差异,实际上可能在性能方面存在缺点


坚持更清晰地说明预期行为的代码,然后只有在存在可测量、可纠正的性能问题时才进行优化。

除了JDB关于异常代价高昂的论点外,请仔细查看您的代码,并告诉我哪些代码更易于阅读/遵循

如果你从未见过一种方法,而它是从一次尝试开始的,那么你真的需要思考并仔细观察。但是,如果它是从您的guard子句If connection==null部分开始的,顺便说一句,这是一件非常常见的事情,您将立即看到,甚至不必认为如果您将null传递到方法中,您将得到一个异常。把这个保护条款当作合同。您永远不希望在其中传递null。这是更好的设计


关于“PS”。如果要执行此操作,请记住,在connection.Close中可能引发的所有其他异常都将被捕获,除非您执行,否则永远不会出现。这些事情可能会让您的应用程序产生难以追踪的bug。

除了JDB认为异常代价高昂之外,请仔细查看您的代码,并告诉我哪些代码更容易阅读/理解

如果你从未见过一种方法,而它是从一次尝试开始的,那么你真的需要思考并仔细观察。但是,如果它是从您的guard子句If connection==null部分开始的,顺便说一句,这是一件非常常见的事情,您将立即看到,甚至不必认为如果您将null传递到方法中,您将得到一个异常。把这个保护条款当作合同。您永远不希望在其中传递null。这是更好的设计


关于“PS”。如果要执行此操作,请记住,在connection.Close中可能引发的所有其他异常都将被捕获,除非您执行,否则永远不会出现。这样的情况可能会使您的应用程序产生很难跟踪的错误。

您的第二个解决方案对性能来说并不是更好,因为当try block导致异常时,您的应用程序将更加努力,catch block将尝试捕获异常。但第二种解决方案在逻辑上要好得多

在第一个解决方案中,当连接为空时,第一次检查时会出现错误

Try-Catch或Try-Catch-Finally是处理错误的强大工具,但代价昂贵。查看此链接以了解如何使用它:

为了获得更好的性能,我将使用:

private static void OpenSqlConnection(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    //Do some work
}
}
上面的示例创建一个SqlConnection,打开它,并执行一些工作。连接将在using块结束时自动关闭

对于Try-catch的代码,我将执行以下操作以捕获异常:

try
{
conn.Close();
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.GetType().FullName);
Console.WriteLine(ex.Message);
//for Asp.net app
//Response.Write(ex.GetType().FullName);
// Response.Write(ex.Message);
}
有关试捕,请参见:

您的Seco nd解决方案对于性能来说并不是更好的,因为当try block导致异常时,应用程序将更加努力,catch block将尝试捕获异常。但第二种解决方案在逻辑上要好得多

在第一个解决方案中,当连接为空时,第一次检查时会出现错误

Try-Catch或Try-Catch-Finally是处理错误的强大工具,但代价昂贵。查看此链接以了解如何使用它:

为了获得更好的性能,我将使用:

private static void OpenSqlConnection(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    //Do some work
}
}
上面的示例创建一个SqlConnection,打开它,并执行一些工作。连接将在using块结束时自动关闭

对于Try-catch的代码,我将执行以下操作以捕获异常:

try
{
conn.Close();
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.GetType().FullName);
Console.WriteLine(ex.Message);
//for Asp.net app
//Response.Write(ex.GetType().FullName);
// Response.Write(ex.Message);
}

关于try-catch,请参见:

是,第二个catch是必需的,因为第一个catch只会捕获ArgumentNullException类型的异常,但不会捕获其他类型的异常,如果有任何异常来回答您的问题-这不是必需的-这是有害的。它正在吞噬任何其他类型的异常。您通常将connection.open代码放在try块中,将connection.close放在finally块中。第二个捕获不是必需的,但对错误日志记录有用。是的,第二个捕获是必需的,因为第一个捕获只捕获ArgumentNullException类型的异常,而不会捕获如果有其他类型的例外来回答你的问题-这不是必要的-这是有害的。它正在吞咽任何其他类型的异常。您通常将connection.open代码放在try块中,将connection.close放在finally块中。第二个捕获不是必需的,但对于错误日志记录非常有用。将ArgumentNullException替换为NullReferenceException,因为当连接==null时,这将是异常。这是我的一个错误。请更新您的答案好吗?@Krowi我已经更新了,但请注意,NullReferenceException通常比ArgumentNullException更糟糕,因为如果不检查堆栈跟踪和查看源代码,您就不知道发生异常的原因。至少对于ArgumentNullException,您知道是哪个参数导致了异常。将ArgumentNullException替换为NullReferenceException,因为当连接==null时,这将是异常。这是我的一个错误。请更新您的答案好吗?@Krowi我已经更新了,但请注意,NullReferenceException通常比ArgumentNullException更糟糕,因为如果不检查堆栈跟踪和查看源代码,您就不知道发生异常的原因。至少对于ArgumentNullException,您知道是哪个参数导致了异常。有趣的方法。对于这个特定的示例,我是否也可以在初始化中执行SqlConnection connection=new SqlConnectionconnectionString和使用connection?是。在代码中,您只是在关闭连接。我的使用示例展示了如何打开和关闭连接,主要是如何在没有任何代码的情况下释放资源。请在这里使用示例进行检查:有趣的方法。对于这个特定的示例,我是否也可以在初始化中执行SqlConnection connection=new SqlConnectionconnectionString和使用connection?是。在代码中,您只是在关闭连接。我的使用示例展示了如何打开和关闭连接,主要是如何在没有任何代码的情况下释放资源。请在此处使用示例进行检查: