【问题标题】:How to dispose managed and unmanaged objects in C#?如何在 C# 中处理托管和非托管对象?
【发布时间】:2016-02-21 17:12:33
【问题描述】:

所有。我从来没有使用过析构函数也没有处理过,所以这对我来说是新的。 我的任务是创建一个具有析构函数和处置方法的类,并且该类具有自动递增的 UInt64 Id 属性和必须由 Id 引用的静态 Dictionary<UInt64,MyClass> all live MyClass 的实例。

在搜索了如何正确使用它们之后,这就是我最终要做的:

public class MyClass : IDisposable
{
    private static Object Lock = new Object();
    private static Dictionary<UInt64, MyClass> LiveInstances = new Dictionary<UInt64, MyClass>();

    public UInt64 Id { get; private set; }

    public MyClass()
    {
        lock (Lock)
        {
            var newId = IncrementalId();
            if (newId == 0)
            {
                throw new ArgumentException("Reached MAX VAL");
            }
            Id = newId;
            LiveInstances.Add(Id, this);
        }
    }

    ~MyClass()
    {
       CleanUpNativeResources();
    }     

    public void Dispose()
    {
        lock (Lock)
        {
            CleanUpManagedResources();
            CleanUpNativeResources();
            GC.SuppressFinalize(this);
        }
    }

    protected virtual void CleanUpManagedResources()
    {
        LiveInstances.Remove(Id);

    }
    protected virtual void CleanUpNativeResources()
    {

    }

    private static UInt64 IncrementalId()
    {
        for (ulong i = 0; i <= Convert.ToUInt64(LiveInstances.Count) ; i++)
        {
            if (i != UInt64.MaxValue && !LiveInstances.ContainsKey(i + 1))
            {
                return i+1;
            }
        }
        return 0;
    }
}

现在,我的问题是如何处置对象?无论我是否尝试查找处置对象的示例,我都会发现类似这样的内容:

 // Code to dispose the managed resources of the class
 Console.WriteLine("Object disposed");

提前致谢。

【问题讨论】:

  • 你没有非托管资源,也没有实现IDisposable的非托管资源,所以你不需要实现IDisposable。垃圾收集器将为您处理一切。
  • 好的。但是如果我想摆脱对象的当前实例呢?我需要创建其他对象并替换已删除的对象(这意味着,它们将使用已删除对象曾经拥有的 Id),并且我不希望我的程序周围具有相同 Id 的对象。

标签: c# asp.net destructor dispose


【解决方案1】:

垃圾收集器会在某个时间点自动释放托管资源。非托管资源类似于文件句柄,通过调用 Windows API 获得,该调用返回必须手动释放的 Windows 句柄。你没有任何需要手动处理的东西。 如果您不释放这些句柄,它们将在程序期间保持分配状态,但所有具有非托管资源的 .Net 类都提供Finalizer(见下文)以确保它们通常会在某些时候被释放点。

(但是,如果您正在编写自己的文件处理类并且忘记在任何地方释放文件句柄,那么文件将保持打开状态,直到您的程序退出。)

通常这些非托管资源会在两个地方被释放:

Dispose() 方法。这应该是您处置非托管资源的正常方式。

终结者。这是最后的机制。如果一个类有一个终结器,那么垃圾收集器在清理死对象时会调用它。如果程序员忘记调用 Dispose(),任何具有非托管资源的类都应该有一个终结器来清理。

使用的基本 Dispose 模式如下所示:

class MyObject : IDisposable
{
    //indicates if dispose has already been called
    //private bool _disposed = false;

    //Finalize method for the object, will call Dispose for us
    //to clean up the resources if the user has not called it
    ~MyObject()
    {
        //Indicate that the GC called Dispose, not the user
        Dispose(false);
    }

    //This is the public method, it will HOPEFULLY but
    //not always be called by users of the class
    public void Dispose()
    {
        //indicate this was NOT called by the Garbage collector
        Dispose(true);

        //Now we have disposed of all our resources, the GC does not
        //need to do anything, stop the finalizer being called
        GC.SupressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        //Check to see if we have already disposed the object
        //this is necessary because we should be able to call
        //Dispose multiple times without throwing an error
        if (!disposed)
        {
            if (disposing)
            {
                //clean up managed resources
                components.Dispose();
            }

            //clear up any unmanaged resources - this is safe to
            //put outside the disposing check because if the user
            //called dispose we want to also clean up unmanaged
            //resources, if the GC called Dispose then we only
            //want to clean up managed resources
        }
    }
}

【讨论】:

  • 好的,这让我对这个主题有了更多的了解。但我有一个疑问:我需要在程序中删除对象的一个​​实例,以便创建一个新实例,稍后,一个新实例将替换它的位置(我的意思是,不能有两个实例具有相同的 ID)。我知道我可以强制调用垃圾收集器,但我也知道这不是推荐的做法。那么,如何删除该实例?只需将其设置为null?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2013-12-14
  • 2014-07-09
相关资源
最近更新 更多