c# - 当 C# 超出范围时,C# 是否自动将 "dispose"IDisposable 对象?

标签 c# asp.net dispose

我正在编写一个 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 被调用,不让事情处理?

事实是,如果我自己没有实现 IDisposableMyObject 类中的内容会因未释放的资源导致泄漏而失败,感觉 .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()) 当 disposingfalse 时。

如果您希望正确处理资源,则需要重构代码。

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/

相关文章:

c# - 用于页面访问控制的 PrincipalPermission 与 web.config

c# - ASP.Net Core Web API 中的返回文件

c# - 如何获取隐藏单元格的值?

java - 关闭框架的最佳方法?

c# - 仍在尝试理解处置模式

Java数据源,如何处置

c# - WebRequest 将 URL 转换为 Xamarin 中的编码 (MonoTouch)

c# - 接口(interface)的使用,实际和现实世界的例子

c# - ASP.NET Claim NameIdentifier Id 获取转换错误

c# - ASP.NET Core 2.0 中 Web API 的本地用户帐户存储