究竟什么是 IDisposable 需要的
本文关键字:IDisposable 什么 究竟 | 更新日期: 2023-09-27 17:56:11
可能的重复项:
正确使用可识别的界面
我试图从书籍、互联网和 stackoverflow 上找到我的问题的实际答案,但到目前为止没有任何帮助,所以希望我能准确地表达我的问题以使其有意义。
总的来说,我总是发现如何释放内存的基本用法相同,大约如下,我确实了解代码本身:
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);
}
}
这些方法的工作方式完全有意义。但是现在我的问题是:为什么我们需要基类ID是可控的?在此代码示例中,我们定义了一个名为 Dispose()
的方法。正如我到处读到的那样,该方法是 IDisposable 的一部分,但我们刚刚在 MyClass
中定义了该方法,如果我们不实现基类 IDisposable 或者我错了这个假设,这段代码仍然有效?
我对 C# 并不完全陌生,但我还有很多东西需要学习,所以希望有人能在这里引导我朝着正确的方向前进。我检查了另一个带有相同问题的帖子,但找不到它,所以如果它确实存在并且它确实回答了我的问题,请带我去那里,我将删除这篇文章。
你是对的,因为你的析构函数~MyClass
调用Dispose
,似乎不需要接口IDisposable
。
但是Dispose
不仅仅是由析构函数调用的。当您希望释放非托管资源时,可以在代码中自行调用它。之所以需要它,是因为您不知道何时调用析构函数(这取决于垃圾回收器)。
最后,当您使用 using
时调用IDisposable.Dispose
。
using(MyDisposableClass myObject = new MyDisposableClass())
{
// My Code
}
相当于:
MyDisposableClass myObject = new MyDisposableClass();
try
{
// My Code
}
finally
{
myObject.Dispose();
}
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
//}
}
实现 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()
它由 C# 编译器与 using
块一起使用。