在使用Using语句处理异常时,是否需要Try/Catch/finally语句来处理异常?

7

我想知道如何使用语句处理异常? 我是否需要将使用语句包装在 Try/Catch/Finally 语句中,以确保即使包含代码引发异常,SqlConnection 对象也会被关闭和处理?

Public Function GetUserAccountKeyByUsername(ByVal pUsername As String) As Int32
    If String.IsNullOrEmpty(pUsername) Then
        Throw New ArgumentNullException("pUsername", "Username is missing")
    End If

    Dim o As Object
    Dim userAccountKey As Int32
    Dim SQL As StringBuilder = New StringBuilder()

    With SQL
        .Append("SELECT USER_KEY ")
        .Append("FROM USER ")
        .Append("WHERE USERNAME = @Username ")
    End With

    Try
        Using conn As SqlConnection = New SqlConnection(ConnectionString)
            conn.Open()
            Using cmd As SqlCommand = New SqlCommand(SQL.ToString, conn)
                Try
                    cmd.CommandTimeout = Convert.ToInt32(ConfigurationManager.AppSettings("SQLQueryLimitTime"))
                    cmd.Parameters.Add(New SqlParameter("@Username", SqlDbType.VarChar)).Value = pUsername
                    o = cmd.ExecuteScalar()
                    If (o IsNot Nothing) AndAlso Not (IsDBNull(o)) Then
                        userAccountKey = Convert.ToInt32(o)
                    End If
                Catch ex As Exception
                    _log.logError(ex, cmd)
                End Try
            End Using
        End Using
    Catch ex As Exception
        _log.logError(ex, conn.ConnectionString)
    Finally
        conn.Close()
        conn.Dispose()
    End Try
    Return userAccountKey
End Function

你还有什么问题吗? - Amar Palsapure
如果您已经获得所需信息,请不要忘记将答案标记为已接受... - Pranay Rana
3个回答

12

using 在你的代码中放置 tryfinally 块,它会自动调用 .Dispose() 方法,最终调用 .Close() 方法,因为 DbConnection.Dispose() 方法调用了 Close() 方法,但是没有 catch 块,所以你需要在 using 块上添加 catch 块,像这样:

try
{
   using(some resource)
   {
   }
}
catch(Exception)
{
}

对比

try
{
}
catch(Exception)
{
}
finally{ }

看起来似乎 Try/Catch/FinallyUsing 更好,因为在 using 中无论如何都需要处理错误,但其实不是这样的。

如果在 .Close().Dispose()期间发生任何错误,第一个示例也会处理该错误,但在第二种情况下,您将不得不在 finally 块中放置 try-catch

了解更多关于避免使用语句时出现问题 (MSDN)

希望这回答了你的问题。


4

您不需要再次编写它,它会在编译代码中自动创建。

答案是使用C#编写的,但在VB.NET中的工作方式相同

C#中的using块在处理一次性对象时非常方便。一次性对象是那些可以在调用dispose时显式释放它们使用的资源的对象。正如我们所知道的,.Net垃圾收集是非确定性的,因此您无法预测对象何时被垃圾收集。

阅读本文以了解更多详细信息:理解C#中的“using”块

CS文件代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BlogSamples
{
    class Program
    {
        static void Main(string[] args)
        {
            using (Car myCar = new Car(1))
            {
                myCar.Run();
            }
        }
    }
}

MSIL代码

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       37 (0x25)
  .maxstack  2
  .locals init ([0] class BlogSamples.Car myCar,
           [1] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  newobj     instance void BlogSamples.Car::.ctor(int32)
  IL_0007:  stloc.0
  .try
  {
    IL_0008:  nop
    IL_0009:  ldloc.0
    IL_000a:  callvirt   instance void BlogSamples.Car::Run()
    IL_000f:  nop
    IL_0010:  nop
    IL_0011:  leave.s    IL_0023
  }  // end .try
  finally
  {
    IL_0013:  ldloc.0
    IL_0014:  ldnull
    IL_0015:  ceq
    IL_0017:  stloc.1
    IL_0018:  ldloc.1
    IL_0019:  brtrue.s   IL_0022
    IL_001b:  ldloc.0
    IL_001c:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0021:  nop
    IL_0022:  endfinally
  }  // end handler
  IL_0023:  nop
  IL_0024:  ret
} // end of method Program::Main

更新关于C#中“using”块的破损理解链接。 - DanElliott

2

是的,你需要使用try catch块,例如在你的代码中记录异常。 using块确保调用Dispose,但不处理异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接