pal*_*wim 2 c# idisposable using-statement
如何在我的函数中返回一个一次性对象以确保它在using块内正常工作?在我的函数中,我想对一次性对象进行操作并考虑错误,这使问题变得复杂。
到目前为止,我有类似于以下代码的内容:
DBHandle GetDB()
{
/* // I can't do this, because the using block would dispose of my object within this function
using( var db = DatabaseObj.GetHandle() )
{
db.Open();
return db;
}
*/
var db = DatabaseObj.GetHandle();
try
{
db.Open();
return db;
}
catch (Exception ex)
{
db.Dispose();
throw ex;
}
}
// In other code:
using( var obj = GetDB() ){ /* ... */ }
Run Code Online (Sandbox Code Playgroud)
提示:当从你的 using 块返回一个一次性对象时,请记住 在执行 return 语句时调用 Dispose() !!!
因此,从 using 块中返回的对象在从函数中出来时就已经被处理掉了。
示例请参见以下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class MyDisposable : IDisposable
{
public void DoSomething()
{
Console.WriteLine(" In DoSomething");
}
#region IDisposable Members
public void Dispose()
{
Console.WriteLine(" In Dispose");
}
#endregion
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting Main\n");
Console.WriteLine("Before NormalMethod");
NormalMethod();
Console.WriteLine("After NormalMethod\n");
Console.WriteLine("Before ReturningMethod");
MyDisposable m = ReturningMethod();
m.DoSomething(); // Here the object already has been disposed!
Console.WriteLine("After ReturningMethod\n");
}
private static void NormalMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
Console.WriteLine(" In NormalMethod");
}
return;
}
private static MyDisposable ReturningMethod()
{
using (MyDisposable myDisposable = new MyDisposable())
{
Console.WriteLine(" In ReturningMethod");
return myDisposable;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将产生以下输出:

你的方法是正确的,但似乎有点不知道如何才是正确的。
考虑一下您(正确地)说无法工作的代码:
DBHandle GetDB()
{
using( var db = DatabaseObj.GetHandle() )
{
db.Open();
return db;
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码几乎相当于:
DBHandle GetDB()
{
var db = DatabaseObj.GetHandle();
try
{
db.Open();
return db;
}
finally
{
if(db != null)//not included if db is a value-type
((IDisposable)db).Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
这里需要注意的一些事情包括 try 直到赋值之后才会发生(同样的情况using- 它不会在 中的赋值之前使您免于异常using)并且这db意味着IDisposable它可以如果该分配无效,则不会编译,并且Dispose()可以隐式或显式实现,并且这两种方式都可以工作。
当然,现在finally无论是否发生异常,块都会执行。您不能使用它using,因为它相当于 afinally并且您只想在发生异常时才Dispose()在您的方法中使用它。因此,你把finally变成了一个catch:
DBHandle GetDB()
{
var db = DatabaseObj.GetHandle();
try
{
db.Open();
return db;
}
catch
{
if(db != null)
((IDisposable)db).Dispose();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
这与您所拥有的几乎相同,除了添加了空检查(也许您可以排除对它的需要)并且我使用的是裸露的throw(当您要重新进行时,这通常是一个好主意)抛出异常而不改变或检查它。在某些情况下,抛出一个新的异常更好,在这种情况下,您应该将原始异常包含InnerException为该新异常的属性,以便为调试人员提供更多信息)。
总而言之,您走在正确的道路上。希望我能帮助解释原因。
| 归档时间: |
|
| 查看次数: |
6569 次 |
| 最近记录: |