using关键字和IDisposable接口有啥关系?
Posted
技术标签:
【中文标题】using关键字和IDisposable接口有啥关系?【英文标题】:What is the relationship between the using keyword and the IDisposable interface?using关键字和IDisposable接口有什么关系? 【发布时间】:2011-04-02 11:11:14 【问题描述】:如果我使用using
关键字,我还需要实现IDisposable
吗?
【问题讨论】:
也许你的意思是,“如果我使用'using'关键字,我还需要调用Dispose()吗? @Chris Farmer...很好的编辑。我开始认为这是@Apple 的新垃圾压实机!!! 正如其他人所指出的,using
语句的控制变量必须是实现IDisposable
的类型。然而,某些方法包含using
语句的事实并不意味着包含这些方法的类必须实现IDisposable
。类实现IDisposable
的最常见原因是它们包含生命周期无法封装在using
语句中的资源。
【参考方案1】:
你不能没有另一个。
当你写的时候:
using(MyClass myObj = new MyClass())
myObj.SomeMthod(...);
编译器会生成类似这样的东西:
MyClass myObj = null;
try
myObj = new MyClass();
myObj.SomeMthod(...);
finally
if(myObj != null)
((IDisposable)myObj).Dispose();
因此,您可以看到,在使用 using
关键字时,假定/要求实现 IDisposable。
【讨论】:
+1,但不假定 - 必需。如果类型未实现 IDisposable,则您在此处显示的编译器代码将出现无效强制转换异常。这就是为什么编译器通过给出编译时错误来防止这种情况发生,使得 IDisposable 需要,而不是假定,用于使用。 @Jimmy 是的,你是对的,假设我是这个意思。答案已更新。【参考方案2】:如果你使用using
statement,封闭的类型必须已经实现IDisposable
,否则编译器会报错。因此,将 IDisposable 实现视为使用的先决条件。
如果你想在你的自定义类上使用using
语句,那么你必须为它实现IDisposable
。然而,这样做有点落后,因为为了它而这样做是没有意义的。只有当你有一些东西需要处理,比如非托管资源时,你才应该实现它。
// To implement it in C#:
class MyClass : IDisposable
// other members in you class
public void Dispose()
// in its simplest form, but see MSDN documentation linked above
这使您能够:
using (MyClass mc = new MyClass())
// do some stuff with the instance...
mc.DoThis(); //all fake method calls for example
mc.DoThat();
// Here the .Dispose method will be automatically called.
实际上这与写作相同:
MyClass mc = new MyClass();
try
// do some stuff with the instance...
mc.DoThis(); //all fake method calls for example
mc.DoThat();
finally // always runs
mc.Dispose(); // Manual call.
【讨论】:
@Troy:添加示例以突出显示说明。 实际上,当您有“三明治”代码必须/应该在 finally 部分执行某些内容时,它是一种非常有用的模式。例如,一个常见的场景是一个忙碌的光标,步骤是... 1./复制现有的光标 2./将光标设置为您的等待光标 3./在最后部分复制回原始光标。使用 using 和 IDisposable,您可以编写类似 using(Busy.WaitCursor) //WaitCursor 是一个静态属性,它返回 Busy 的实例,构造函数复制和设置,并且 dispose() 重新设置。 @Tim - 另一个很好的例子是更改控制台应用程序的颜色(我想我在 Wes Dyer 的博客上看到了这一点)。对于这样的任务,实现一个 Disposable 类有时很有用,该类简单地包装了一个在 Dispose() 上执行的 Action。但是,有时我不禁觉得它有点反模式。我想知道其他人对通用 Disposable 类的主题有何看法。【参考方案3】:你把事情弄糊涂了。您只能在实现 IDisposable 的东西上使用“using”关键字。
编辑:如果使用 using 关键字,则不必显式调用 Dispose,它将在 using 块的末尾自动调用。其他人已经发布了如何将 using 语句转换为 try - finally 语句的示例,并在 finally 块中调用 Dispose。
【讨论】:
从记录集中读取数据时可以使用“using”关键字,对吗? @Troy,是的,那是因为 IDataReader 实现了 IDisposable。 只有当包装你的记录集的任何东西都实现了 IDisposable 时。如果它编译然后它实现 IDisposable....【参考方案4】:是的,using 关键字是这种模式的语法糖......(来自 msdn)
Font font1 = new Font("Arial", 10.0f);
try
byte charset = font1.GdiCharSet;
finally
if (font1 != null)
((IDisposable)font1).Dispose();
编辑:一个有用的例子。
当您发现您在 finally 部分中始终如一地执行操作时,例如在将光标设置为等待光标后将其重置为默认值时,这是此模式的候选者...
public class Busy : IDisposable
private Cursor _oldCursor;
private Busy()
_oldCursor = Cursor.Current;
public static Busy WaitCursor
get
Cursor.Current = Cursors.WaitCursor;
return new Busy();
#region IDisposable Members
public void Dispose()
Cursor.Current = _oldCursor;
#endregion
叫...
using(Busy.WaitCursor)
// some operation that needs a wait cursor.
【讨论】:
【参考方案5】:Using 只会处理 disposable 对象。因此,在没有实现 IDisposable 相当无用的对象周围包装 using 块实际上会导致编译器错误。
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
通常,当您使用 IDisposable 反对,你应该声明和 在 using 语句中实例化它。 using 语句调用 Dispose 正确的对象上的方法 方式,它也会导致对象 自己尽快超出范围 调用处置。使用范围内 块,该对象是只读的,并且 无法修改或重新分配。
using 语句确保 即使出现异常也会调用 Dispose 在您调用方法时发生 物体上。你可以实现 通过放置对象获得相同的结果 在 try 块内,然后调用 在 finally 块中处理;实际上, 这就是 using 语句的方式 由编译器翻译。
【讨论】:
【参考方案6】:您必须实现 IDisposable 才能使用 using。如果您尝试在未实现 IDisposable 的类型上使用 using(),则会收到以下编译时错误:
error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable'
【讨论】:
【参考方案7】:using 关键字已经实现,所以如果使用 using 关键字,则不必调用 IDisposable
【讨论】:
以上是关于using关键字和IDisposable接口有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章