使用C#的'using'语句和自定义对象的函数,我是否需要实现IDisposable?

时间:2022-09-02 13:49:18

I have an sqlConnection manager class like so:

我有一个像这样的sqlConnection管理器类:

public class SQLConn {
  public string connStr = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"];

  private SqlConnection sqlConn;

  public SqlConnection Connection()
  {
      sqlConn = new SqlConnection(connStr);

      return sqlConn;
  }

  public void Open()
  {
        sqlConn .Open();
  }
}

If I use a function with the 'using' statement like:

如果我使用'using'语句的函数,如:

var conn = new SQLConn();

using (conn.Connection()) 
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, conn.Connection());      

    conn.Open(); 
    DoSomething(); 
}

Does the using statement dispose of the connection automatically since conn.Connection() returns a SqlConnection object? Or, do I have to implement IDisposable and a custom Dispose method on the SqlConn class?

由于conn.Connection()返回SqlConnection对象,using语句是否会自动处理连接?或者,我是否必须在SqlConn类上实现IDisposable和自定义Dispose方法?

Is this even a good way at all? I'm working with legacy code and I'm not able to use an ORM yet but is there a way to simplify this existing pattern to manage/create SQL connections?

这甚至是一个好方法吗?我正在使用遗留代码,但我还无法使用ORM,但有没有办法简化现有模式来管理/创建SQL连接?

8 个解决方案

#1


The using statement will look at the final type of the expression - i.e. whatever is returned from .Connection(); if this returns something that is IDisposable, then you're OK.

using语句将查看表达式的最终类型 - 即从.Connection()返回的内容;如果这返回IDisposable的东西,那么你没关系。

The compiler will tell you if you get it wrong ;-p (it won't let you use using on something that isn't IDisposable).

如果你弄错了,编译器会告诉你;-p(它不允许你在不能使用IDisposable的东西上使用它)。

You should probably watch out for where you are creating two connections:

您应该注意创建两个连接的位置:

using (var c = conn.Connection()) // <==edit
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, c); // <==edit

    c.Open(); 
    DoSomething(); 
}

and possibly:

public SqlConnection Connection()
{
  if(sqlConn == null) sqlConn = new SqlConnection(connStr); // <== edit
  return sqlConn;
}

#2


It will work but after the using {} you will be left with an sqlConn that internally holds a Disposed SqlConnection. Not a really useful situation

它会工作但是在使用{}之后你会留下一个内部持有Disposed SqlConnection的sqlConn。不是一个非常有用的情况

#3


Your code is wrong!

你的代码错了!

shoudl be something like this:

shoudl是这样的:

Dim conn as New SQLConn();
Dim sqlConnection New SQLConnection();

sqlConnection = conn.Connection();

using (sqlConnection) 
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, sqlConnection);      

    conn.Open(); 
    DoSomething(); 
}

That way the using statement will dispose the connection at the end.

这样,using语句将在最后处置连接。

#4


To clarify what is being said above:

澄清上面说的是什么:

Any object you need to use with using should be disposed at the end of the using statement. The compiler thus need to make sure that your type implements the IDisposable interface when it sees using on that type object or it won't let you go.

您需要使用的任何对象都应该在using语句的末尾处理。因此,编译器需要确保您的类型在看到使用该类型对象时实现IDisposable接口,否则它将不允许您离开。

#5


to answer your headline question, you must implement IDisposable in the class whose object you're using with "using". Otherwise, you'll get a compile-time error.

要回答您的标题问题,您必须在您正在使用“使用”对象的类中实现IDisposable。否则,您将收到编译时错误。

Then, yes, "using" will dispose your SqlConnection at the end of the block. Think of "using" as a "try-finally": there is an implicit call to Dispose() in the "finally" block.

然后,是的,“使用”将在块的末尾处置您的SqlConnection。将“using”视为“try-finally”:在“finally”块中隐式调用Dispose()。

Finally, cleaner code would be:

最后,更清洁的代码将是:

using( SqlConnection = new SqlConnection( connStr ) {
    // do something
}

At least readers of your code won't have to make the mental effort to realize as Henk Holterman pointed out that your SQLConn object holds a reference to a disposed connection.

至少你的代码的读者不必费心去实现,因为Henk Holterman指出你的SQLConn对象持有对已处置连接的引用。

#6


No you do not, as long as the returned object is IDisposable.

不,你没有,只要返回的对象是IDisposable。

The returned object needs not to implement IDisposable, but then the using block would serve no purpose.

返回的对象不需要实现IDisposable,但是使用块没有用处。

#7


From MSDN:

The object provided to the using statement must implement the IDisposable interface.

提供给using语句的对象必须实现IDisposable接口。

You do not have to call Dispose() though, the using statement implicitly does this for you.

您不必调用Dispose(),using语句隐式为您执行此操作。

#8


It seems the connection will be closed properly, but this is not recommended:

似乎连接将正确关闭,但不建议这样做:

You can instantiate the resource object and then pass the variable to the using statement, but this is not a best practice. In this case, the object remains in scope after control leaves the using block even though it will probably no longer have access to its unmanaged resources. In other words, it will no longer be fully initialized. If you try to use the object outside the using block, you risk causing an exception to be thrown. For this reason, it is generally better to instantiate the object in the using statement and limit its scope to the using block.

您可以实例化资源对象,然后将变量传递给using语句,但这不是最佳实践。在这种情况下,在控制离开使用块之后,对象仍然在范围内,即使它可能不再能够访问其非托管资源。换句话说,它将不再完全初始化。如果您尝试使用using块之外的对象,则可能会导致抛出异常。因此,通常最好在using语句中实例化对象,并将其范围限制为using块。

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

#1


The using statement will look at the final type of the expression - i.e. whatever is returned from .Connection(); if this returns something that is IDisposable, then you're OK.

using语句将查看表达式的最终类型 - 即从.Connection()返回的内容;如果这返回IDisposable的东西,那么你没关系。

The compiler will tell you if you get it wrong ;-p (it won't let you use using on something that isn't IDisposable).

如果你弄错了,编译器会告诉你;-p(它不允许你在不能使用IDisposable的东西上使用它)。

You should probably watch out for where you are creating two connections:

您应该注意创建两个连接的位置:

using (var c = conn.Connection()) // <==edit
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, c); // <==edit

    c.Open(); 
    DoSomething(); 
}

and possibly:

public SqlConnection Connection()
{
  if(sqlConn == null) sqlConn = new SqlConnection(connStr); // <== edit
  return sqlConn;
}

#2


It will work but after the using {} you will be left with an sqlConn that internally holds a Disposed SqlConnection. Not a really useful situation

它会工作但是在使用{}之后你会留下一个内部持有Disposed SqlConnection的sqlConn。不是一个非常有用的情况

#3


Your code is wrong!

你的代码错了!

shoudl be something like this:

shoudl是这样的:

Dim conn as New SQLConn();
Dim sqlConnection New SQLConnection();

sqlConnection = conn.Connection();

using (sqlConnection) 
{ 
    String query = "Select * from table";
    objSql = new SqlCommand(query, sqlConnection);      

    conn.Open(); 
    DoSomething(); 
}

That way the using statement will dispose the connection at the end.

这样,using语句将在最后处置连接。

#4


To clarify what is being said above:

澄清上面说的是什么:

Any object you need to use with using should be disposed at the end of the using statement. The compiler thus need to make sure that your type implements the IDisposable interface when it sees using on that type object or it won't let you go.

您需要使用的任何对象都应该在using语句的末尾处理。因此,编译器需要确保您的类型在看到使用该类型对象时实现IDisposable接口,否则它将不允许您离开。

#5


to answer your headline question, you must implement IDisposable in the class whose object you're using with "using". Otherwise, you'll get a compile-time error.

要回答您的标题问题,您必须在您正在使用“使用”对象的类中实现IDisposable。否则,您将收到编译时错误。

Then, yes, "using" will dispose your SqlConnection at the end of the block. Think of "using" as a "try-finally": there is an implicit call to Dispose() in the "finally" block.

然后,是的,“使用”将在块的末尾处置您的SqlConnection。将“using”视为“try-finally”:在“finally”块中隐式调用Dispose()。

Finally, cleaner code would be:

最后,更清洁的代码将是:

using( SqlConnection = new SqlConnection( connStr ) {
    // do something
}

At least readers of your code won't have to make the mental effort to realize as Henk Holterman pointed out that your SQLConn object holds a reference to a disposed connection.

至少你的代码的读者不必费心去实现,因为Henk Holterman指出你的SQLConn对象持有对已处置连接的引用。

#6


No you do not, as long as the returned object is IDisposable.

不,你没有,只要返回的对象是IDisposable。

The returned object needs not to implement IDisposable, but then the using block would serve no purpose.

返回的对象不需要实现IDisposable,但是使用块没有用处。

#7


From MSDN:

The object provided to the using statement must implement the IDisposable interface.

提供给using语句的对象必须实现IDisposable接口。

You do not have to call Dispose() though, the using statement implicitly does this for you.

您不必调用Dispose(),using语句隐式为您执行此操作。

#8


It seems the connection will be closed properly, but this is not recommended:

似乎连接将正确关闭,但不建议这样做:

You can instantiate the resource object and then pass the variable to the using statement, but this is not a best practice. In this case, the object remains in scope after control leaves the using block even though it will probably no longer have access to its unmanaged resources. In other words, it will no longer be fully initialized. If you try to use the object outside the using block, you risk causing an exception to be thrown. For this reason, it is generally better to instantiate the object in the using statement and limit its scope to the using block.

您可以实例化资源对象,然后将变量传递给using语句,但这不是最佳实践。在这种情况下,在控制离开使用块之后,对象仍然在范围内,即使它可能不再能够访问其非托管资源。换句话说,它将不再完全初始化。如果您尝试使用using块之外的对象,则可能会导致抛出异常。因此,通常最好在using语句中实例化对象,并将其范围限制为using块。

http://msdn.microsoft.com/en-us/library/yh598w02.aspx