关于范围的 C# 内存分配/取消分配问题

标签 c# memory-management

我最近正在阅读一篇垃圾收集文章,并决定一起玩并尝试获得更深入的理解。我编写了以下代码,尝试使用 using 语句,但对结果感到惊讶......我预计 using block 之外的 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");
            }
        }

最佳答案

您的 Dispose 方法实际上不会对 Parent 的实例执行任何操作,因此它仍然是公平的游戏/作为类的可用实例工作。

IDisposable 通常在您的类持有非托管资源(例如数据库连接或文件)时使用,以便在 Dispose() 时可以将其清除叫做。仅调用 Dispose 不会对非托管资源执行任何操作,方法中必须有一些代码对这些资源执行某些操作。虽然 c# 可能具有 using() {} 语法来将 IDisposable 对象的实例化和处置包装在 try/catch/finally 中,但这并不意味着它会执行任何操作“特殊”与处置对象。

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

public void Dispose()
{
    Name = null;
    Console.WriteLine("Disposing Parent");
}

因为您已将 p 分配给 e.Parent,对象本身仍然“在范围内”,因为有对它的引用,因此它仍然可以访问 Console.WriteLine(e.Parent.Name); 从中生成输出。

目前“CLR 周”也在 The Old New Thing 结束了本周的前 3 篇文章讨论了垃圾收集器及其工作/行为方式。它们非常值得一读:

关于关于范围的 C# 内存分配/取消分配问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3453446/

相关文章:

c# - 测试 C# MySQL 连接池失败并出现异常 : Connection must be valid and open

c# - 获取 Content-Disposition 参数

c# - 如何清除 WPF RichTextBox?

c++ - C 与 C++ 在内存分配方面的性能

ios - Swift 对象的安全内存

c# - 如何最好地命名字段和属性

c# - 使用 C# 中的 v4 函数应用从 Azure 表存储获取包含所有数据集的完整表

c++ - 一个关于内存使用的简单C++问题

c - 重置 C 中的字符缓冲区

c++ - new 和 delete 超出范围的内存管理