将 C# 的“using”语句与自定义对象的函数一起使用,是否需要实现 IDisposable?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/915022/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using C#'s 'using' statement with a custom object's function, do I Need to implement IDisposable?
提问by zulkamal
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 连接?
采纳答案by Marc Gravell
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 (它不会让你使用using
不是的东西IDisposable
)。
You should probably watch out for where you are creating twoconnections:
您可能应该注意创建两个连接的位置:
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;
}
回答by leppie
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,但是 using 块将无用。
回答by annakata
回答by Henk Holterman
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
它会工作,但之后using {}
你将留下一个内部持有一个 Disposed SqlConnection 的 sqlConn。不是一个真正有用的情况
回答by Pavel Nikolov
Your code is wrong!
你的代码错了!
shoudl be something like this:
应该是这样的:
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 语句将在最后处理连接。
回答by Alexander Prokofyev
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 语句中实例化对象并将其范围限制为 using 块。
回答by azheglov
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 对象持有对已处理连接的引用。
回答by Yohanis
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 一起使用的任何对象都应在 using 语句的末尾处理。因此,编译器需要确保您的类型在该类型对象上看到 using 时实现了 IDisposable 接口,否则它不会让您离开。