即使对象超出范围,Dotnet也不会调用它的终结器.那么如何释放非托管资源呢?

S.F*_*rrd 0 c# unmanaged unmanagedresources

我尝试使用以下代码

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateNode();

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void ReleaseNode(IntPtr handle);

 class Node
{
    IntPtr nativePtr;
    public int id;
    public Node(int i)
    {
        nativePtr = CreateNode();
        id = i;
        Debug.WriteLine("Constructed " + id);
    }

    ~Node()
    {
        ReleaseNode(nativePtr);
        Debug.WriteLine("Destructed " + id);
    }
}

    class Program
    {
        static void Main(string[] args)
        {

            for (int i = 0; i < 10; i++)
            {
                Node n = new Node(i);
            } //this scope
        }
    }
Run Code Online (Sandbox Code Playgroud)

Nodefor循环内部创建的类的每个对象在离开for循环范围后都没有被破坏(被称为"此范围").只有当Main方法的范围结束时才会调用它.当for循环范围结束时,是否可以自动调用〜节点?

在执行上面的代码时,我在调试窗口中得到以下内容.

Constructed 0
Constructed 1
Constructed 2
Constructed 3
Constructed 4
Constructed 5
Constructed 6
Constructed 7
Constructed 8
Constructed 9
Destructed 9
Destructed 0
Destructed 8
Destructed 7
Destructed 6
Destructed 5
Destructed 4
Destructed 3
Destructed 2
Destructed 1
Run Code Online (Sandbox Code Playgroud)

这表明首先构造的对象在最后被破坏了.如果发生这种情况,当我在循环中运行数千个项目时会发生什么?它会消耗我所有的记忆吗?

如何完美释放我的非托管资源?

Jon*_*eet 6

TL; DR:如果可能的话,摆脱终结器,只要相信垃圾收集器做正确的事情.

最终确定是非确定性的.重要的是要理解对象不会超出范围; 对象没有可以开始的范围.变量超出范围,并且不会触发任何内容.

通常,垃圾收集器只在需要时运行.无法保证调用终结器的顺序,或者它们何时被调用.(虽然你可以请求垃圾收集器运行,但这通常是一个坏主意并且几乎没有任何保证.)

在你自己的课程中有一个终结器几乎总是一个坏主意:它延迟了实际的垃圾收集,并且几乎总是有更好的方法来处理你在终结器中做的任何事情.