C#关于范围的内存分配/解除分配问题

Mik*_* M. 5 c# memory-management

我最近浏览了一篇垃圾收集文章并决定一起玩,并试图获得更多的理解.我编写了以下代码,玩弄了using声明,但对结果感到惊讶......我期望在使用块之外的e.Parent.Name会变成ka-blooey.

到底发生了什么?

static void Main(string[] args)
        {
            Employee e = new Employee();

            using (Parent p = new Parent())
            {
                p.Name = "Betsy";
                e.Parent = p;
                Console.WriteLine(e.Parent.Name);
            }

            Console.WriteLine(e.Parent.Name);            

            Console.ReadLine();
        }

        public class Employee
        {
            public Parent Parent;
        }

        public class Parent : IDisposable
        {
            public string Name;

            public void Dispose()
            {
                Console.WriteLine("Disposing Parent");
            }
        }
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 10

你的Dispose方法实际上并没有对实例做任何事情Parent,因此它仍然是公平的游戏/作为一个类的可用实例.

IDisposable当您的类保留在非托管资源(例如数据库连接或文件)上时,通常会使用它,以便在Dispose()调用时可以清除它.只是调用Dispose对非托管资源没有任何作用,方法中必须有一些代码可以对这些资源执行某些操作.虽然c#可能具有在try/catch/finally中using() {}包装实例化和处理IDisposable对象的语法,但这并不意味着它对被处置对象执行任何"特殊"操作.

假设,假设这Name实际上是一个非托管资源,而不仅仅是一个字符串,您的Dispose()方法可以读取:

public void Dispose()
{
    Name = null;
    Console.WriteLine("Disposing Parent");
}
Run Code Online (Sandbox Code Playgroud)

因为你已经分配pe.Parent,所以对象本身仍然是"在范围内",因为它有一个对它的引用,因此它仍然可以Console.WriteLine(e.Parent.Name);从中产生输出.

它现在也是The Old New Thing的 "CLR Week",本周的前三篇文章讨论了垃圾收集器及其工作原理.他们非常值得一读: