IDisposable 到底需要啥? [复制]
Posted
技术标签:
【中文标题】IDisposable 到底需要啥? [复制]【英文标题】:What exactly is IDisposable needed for? [duplicate]IDisposable 到底需要什么? [复制] 【发布时间】:2013-01-11 07:53:48 【问题描述】:可能重复:Proper use of the IDisposable interface
我试图从书籍、互联网和 *** 上找到我的问题的实际答案,但到目前为止没有任何帮助我,所以希望我能准确地表达我的问题以使其有意义。
一般来说,我总是发现如何释放内存的基本用法相同,大约是。如下,我确实理解代码本身:
public class MyClass : IDisposable
bool disposed = false;
public void Dispose()
if (!disposed)
Dispose(true);
GC.SuppressFinalize(this);
disposed = true;
protected virtual void Dispose(bool disposing)
if (disposing)
//free managed ressources
// free other ressources
~MyClass()
Dispose(false);
方法的工作方式完全有意义。但现在我的问题是:为什么我们需要基类 IDisposable?在此代码示例中,我们定义了一个名为 Dispose()
的方法。正如我在各处读到的那样,该方法是 IDisposable 的一部分,但我们刚刚在 MyClass
中定义了该方法,如果我们不实现基类 IDisposable 或者我对这个假设有误,这段代码仍然可以工作?
我对 C# 并不完全陌生,但我还有很多东西要学,所以希望有人能在这里引导我朝着正确的方向前进。我检查了另一个具有相同问题的帖子,但找不到它,所以如果它确实存在并且它确实回答了我的问题,请引导我到那里,我将删除此帖子。
【问题讨论】:
IDisposable 不是 [base] 类。这是一个interface。为什么在 C# 中需要 any 接口? (IDisposable 的作用不亚于其他接口。) 感谢您的快速回复。好吧,既然我还有很多关于 C# 的知识,请回答你刚才问我的问题。 感谢您的链接,在我看来,讽刺有点不必要。我不知道基类和接口之间有如此大的区别 在任何情况下,接口都提供了一个主名类型(通过给定名称已知的类型/契约)而不影响对象的类层次结构。这允许在同一接口中使用不同类型的对象;一些接口,如 IDisposable(或 ISerializable)也建立了各种使用“规则和模式”。请参阅相应的文档。 我们能否减少重复的回答? 【参考方案1】:它与 C# 编译器的 using
块一起使用。
【讨论】:
虽然我不认为这是一个“完整”的答案,但using
(以及通过Dispose()
进行的更多手动生命周期管理)是IDisposable
的唯一原因......所以+1。
【参考方案2】:
IDisposable.Dispose 的实际实现调用了 Dispose(bool) 的基类实现。从这个类继承的任何人现在都需要处理以下任务:
public override Dispose(bool disposing)
base.Dispose(disposing);
//my disposal code
使用这种公认的模式,继承者可以在不破坏基类的处置的情况下扩展处置代码。
通常,如果您没有非托管资源可以处置并且可以负担得起您的课程,您可以使用以下代码简化问题:
public sealed class SomeDisposable:IDisposable
public void Dispose()
//just go ahead and clean up
//because we're sealed, no-one can ever break
//this code via inheritance
//~SomeDisposable()
//
// if this is being called then it will be called
// on all referenced and unrooted IDisposables too
// If everything is managed, that means we've got nothing
// left to clean up, so we can omit this Finalizer
//
【讨论】:
感谢和 +1 添加密封类。【参考方案3】:你是对的,因为你的析构函数~MyClass
调用Dispose
,似乎不需要接口IDisposable
。
但Dispose
不仅仅由析构函数调用。当您想要释放非托管资源时,您可以在代码中自己调用它。之所以需要它,是因为您不知道何时调用析构函数(这取决于垃圾收集器)。
最后,IDisposable.Dispose
在您使用 using
时被调用。
using(MyDisposableClass myObject = new MyDisposableClass())
// My Code
相当于:
MyDisposableClass myObject = new MyDisposableClass();
try
// My Code
finally
myObject.Dispose();
【讨论】:
这是一个很好的解释,感谢您的快速澄清 您也不能显式调用 C# 类析构函数。它首先在 GC 启动时调用,而不是 .Dispose() ,后者通常由用户代码显式调用。【参考方案4】:实施 IDispose 为您提供了一个地方来释放您“持有”的资源,例如流、句柄或数据库连接。
从垃圾收集器调用Dispose(),基本上是询问对象:“如果有什么你不再需要,但我想不通;现在释放它;清理!”
在某种意义上类似于 C++ 中的析构函数
不同之处在于 C++ 的析构函数会立即被调用,而 Dispose() 会更及时。
在大多数情况下,您不需要实现它。 GC 足够聪明,可以在 90% 的情况下找出如何释放已用资源。
但是例如:释放流使用的内存并不会自动关闭 流并释放数据库连接也不会关闭它。
实现 Dispose 允许您在释放对象时关闭文件:
internal class Something : IDisposable
private Stream stream;
public void SomeMethod()
stream.Write("nskdns");
public void Dispose()
if (stream != null)
stream.Close();
此外:实现 IDispose 让您有机会在 using 语句中使用类:
public void Example()
using (var x = new Something())
x.SomeMethod();
确保 x 在被 GC 释放时总是会关闭已使用的流。
我更喜欢类上的专用 Close() 方法,以允许显式关闭流,而不是依赖 GC 并调用 Dispose()
【讨论】:
以上是关于IDisposable 到底需要啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
c# 中最简单的 IDisposable 模式是啥? [复制]
使用 Spring Data JPA 的 JpaRepository 和 CrudRepository 之间到底有啥区别? [复制]