我正在编写一个 ASP.NET Web API。作为其中的一部分,我有一个类,我在测试期间发现它需要实现 IDisposable
以确保释放托管资源。
因此,我在我的类中实现了IDisposable
,并将释放资源所需的代码放在Dispose()
方法中。
我的代码中有很多地方(数百个)实例化了这个对象,并在同一行中调用了新实例的方法。我只需要实例来调用单一方法。
这是一个例子:
// MyObject, a class that needs to be disposed of.
public class MyObject : IDisposable
{
private AnObjectThatMustBeDisposed localObject;
public MyObject()
{
localObject = SomeLibrary.SomeProject.AnObjectThatMustBeDisposed.Create();
}
public void doOperationOne()
{
localObject.DoSomething(1);
}
public string getOperationTwo()
{
return localObject.DoSomething(2);
}
public string getOperationThree()
{
return localObject.DoSomething(3);
}
public bool getOperationFour(string input)
{
return localObject.DoSomethingSpecial(4,input.ToLower());
}
...
public void getOperationOneHundred(DateTime input)
{
localObject.DoSomethingElse(100,input);
}
public void Dispose()
{
localObject.CloseResources();
localObject.FreeUpMemory();
localObject.Close();
localObject.Dispose();
}
}
// A class that makes use of MyObject
public class MyLibraryThatUsesMyObject
{
public void Method1()
{
new MyObject().doOperationOne();
}
public string Method2()
{
return new MyObject().getOperationTwo();
}
public int Method3()
{
return new MyObject().getOperationThree();
}
public bool Method4(string testString)
{
if (testString.Length > 6)
{
if (new MyObject().getOperationFour(testString)) return true;
else return false;
}
else return false;
}
...
public void Method100()
{
new MyObject().doOperationOneHundred(DateTime.Now);
}
}
我的问题是:当对象超出范围时,.NET 会自动 Dispose()
对象吗?或者,我真的必须这样做......
public void Method1()
{
using (MyObject o = new MyObject())
{
o.DoOperationOne();
}
}
...每种方法?如果我有两个或三个方法并不难,但如果我有大量方法,这种重构可能需要相当长的时间。
我不确定 ASP.NET 在请求完成时如何处理请求 - 即框架是否为 Dispose()
事物提供代码时间,或者它是否在 return
被调用,不让事情处理?
事实是,如果我自己没有实现 IDisposable
,MyObject
类中的内容会因未释放的资源导致泄漏而失败,感觉 .NET 不会 自动 Dispose
东西。那么,如果是这样的话,我是否可以做一些事情而不必重构数百个方法?
编辑:我尝试简单地实现IDisposable
,但我的单元测试仍然能够产生资源泄漏。因此,我对 .NET 不会自动处理的怀疑似乎是正确的。所以现在我的问题变成了 - 如何在不必重构数百种方法的情况下强制处置?
最佳答案
Dispose 不会自动调用。如果您不调用 .Dispose()
(无论是显式调用还是通过 using
语句),该方法将永远不会被调用。
唯一需要注意的是使用模式实现的方法
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
~MyClass()
{
Dispose(false);
}
bool _isDisposed = false;
protected virtual void Dispose(bool disposeing)
{
if(_isDisposed)
return;
_isDisposed = true;
if(disposing)
{
//Disposed managed code here
}
//Dispose unmanaged code only here.
}
当对象最终确定时,将调用 Dispose(false)
,但不允许您处置(甚至访问)托管对象(即:其他实现 的东西。 Dispose()
) 当 disposing
为 false
时。
如果您希望正确处理资源,则需要重构代码。
Stephen Cleary 写了一篇非常非常好的文章“IDisposable: What Your Mother Never Told You About Resource Deallocation”,它很好地解释了 Dispose 的工作原理以及如何正确编写您自己的可处理对象(例如, 我上面提到的警告模式是微软推荐的,但实际上是一个非常糟糕的模式。类应该只持有托管资源或从 SafeHandle
派生并且只持有非托管资源和可能的其他 SafeHandles
。你不应该有一个类同时包含托管和非托管资源,也不应该有一个类包含多个非托管资源)
关于c# - 当 C# 超出范围时,C# 是否自动将 "dispose"IDisposable 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43420323/