程序化检查或 try...catch

Programmatic check or try...catch

我这里有一些代码:

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。 catch (Exception exception) { } 有必要吗?

编辑:在第二个代码中将 ArgumentNullException 替换为 NullReferenceException 因为当 connection == null.

时那将是例外

根据 Microsoft 的说法,异常会严重影响性能。在合理的情况下尽量避免使用它们:

Throwing exceptions can be very expensive, so make sure that you don't throw a lot of them. Use Perfmon to see how many exceptions your application is throwing. It may surprise you to find that certain areas of your application throw more exceptions than you expected. For better granularity, you can also check the exception number programmatically by using Performance Counters.

Finding and designing away exception-heavy code can result in a decent perf win. Bear in mind that this has nothing to do with try/catch blocks: you only incur the cost when the actual exception is thrown. You can use as many try/catch blocks as you want. Using exceptions gratuitously is where you lose performance. For example, you should stay away from things like using exceptions for control flow.

https://msdn.microsoft.com/en-us/library/ms973839.aspx#dotnetperftips_topic2

你的第二个例子实际上是一个更糟糕的场景。您几乎不应该捕获一般异常。你可能认为你知道会抛出什么,但很有可能反而会抛出一些意想不到的东西,导致系统不稳定和可能的数据loss/corruption.

It's Still Wrong to Use Catch (Exception e)

Even though the CLR exception system marks the worst exceptions as CSE, it's still not a good idea to write catch (Exception e) in your code. Exceptions represent a whole spectrum of unexpected situations. The CLR can detect the worst exceptions—SEH exceptions that indicate a possibly corrupt process state. But other unexpected conditions can still be harmful if they are ignored or dealt with generically.

In the absence of process corruption, the CLR offers some pretty strong guarantees about program correctness and memory safety. When executing a program written in safe Microsoft Intermediate Language (MSIL) code you can be certain that all the instructions in your program will execute correctly. But doing what the program instructions say to do is often different from doing what the programmer wants. A program that is completely correct according to the CLR can corrupt persisted state, such as program files written to a disk.

https://msdn.microsoft.com/en-us/magazine/dd419661.aspx

I wonder if the next code would be a better solution performance wise

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

  1. connection 为空

您将得到 NullReferenceException 而不是 ArgumentNullException,这是功能上的差异,因为您会得到不同的异常类型(并且 less 上下文why/where异常发生)。如果您决定捕获 NullReferecenException 并抛出 ArgumentNullException,那么您就有抛出 new 异常的开销,因此会影响性能。

  1. 连接未关闭。

尝试关闭连接 - 此处没有真正的性能或功能差异。

  1. 连接已关闭

您尝试再次关闭连接。这里可能没有很大的功能差异(因为如果您尝试关闭已经关闭的连接,大多数提供商可能不会生气),但它 不必要 并且可能有一些性能缺点,具体取决于Close() 方法实际上 做了什么

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

坚持使用能够更清晰地说明预期行为的代码 - 然后仅在存在可衡量、可纠正的性能问题时才进行优化。

除了 JDB 关于异常成本高昂的论点之外,请仔细查看您的代码并告诉我其中哪些更容易 read/follow?

如果您从未见过以 "try" 开头的方法,那么您真的需要仔细思考并仔细观察。但是,如果它以您的保护子句( if (connection == null) 部分)开头,顺便说一下,这是一件很常见的事情,您会立即看到,甚至不必考虑如果您通过 null进入方法你会得到一个例外。将此保护条款视为合同。您永远不希望将 null 传递到那里。这是更好的设计。

关于'PS'。如果您要这样做,请记住可能在 connection.Close() 中抛出的所有其他异常都将被捕获,并且除非由您完成,否则永远不会浮出水面。这些事情可能会使您的应用程序产生很难追踪的错误。

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

在您的第一个解决方案中,当连接为空时,您将在第一次检查时收到错误消息。

Try-Catch 或 Try-Catch-Finally 是处理错误的强大工具,但它们很昂贵。看看这个 link 看看你能用它做什么:Using 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请看:this link - Best Practices for Exceptions