你为什么还能使用被处置物?

时间:2016-03-06 09:38:30

标签: c# oop

我正在努力了解处理对象和垃圾收集。特别是,我不明白为什么我仍然可以使用处置对象。我实际上并没有尝试做任何事情,我现在只是在玩理论,在我的理解中,我认为我无法做到以下几点:

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        using (p)
        {
            p.Name = "I am Name";
        }
        Console.WriteLine(p.Name); // I thought this would break because I've already disposed of p
        Console.ReadLine();
    }
}
public class Person : IDisposable
{
    public string Name;
    public void Dispose()
    {
        Console.WriteLine("I got killed...");
    }
}

我希望有人可以在这里给我一些指导或指导,以便澄清我对这个概念的误解?

3 个答案:

答案 0 :(得分:7)

处理对象并没有做任何神奇的事情 - CLR根本不关心IDisposable ......它只是一个在C#中有支持的框架接口(和其他语言)。调用Dispose就像调用其他方法一样。

如果您在执行进一步操作时没有生成配置对象失败,则不会失败。实际上,在某些情况下,您确实想要能够 - 例如,在ToArray上调用MemoryStream之后,即使您处置了Read也没问题。无法调用MemoryStream等。对于MemoryStream的写入是从包含def translate(self, delta_x, delta_y): if not isinstance(delta_x, float): 的包装器链接的情况下,这可能非常方便,但是你想要之后的数据。

一般情况下,您应该编码,好像您可以在处置后使用已处置的对象,除非您确定它仍然支持您需要的操作。默认位置"我预计会破坏..."是安全的。

答案 1 :(得分:4)

当您拥有使用非托管资源的对象时,将使用Dispose模式,该对象需要在不再需要时释放。 GC自动释放托管资源。

在您的示例中,字符串Name是受管资源。如果那里有一个打开的文件,那将是一个非托管资源。然后,Dispose方法将关闭关闭文件句柄,这将使对象的文件访问在Dispose之后不可用。然而,你可以要求提供名称,因为在GC收集该对象之前,它将存在。

推荐阅读:MSDN Dispose Pattern

答案 2 :(得分:1)

IDisposable是处理托管代码中的非托管资源的惯例。

您正在实施IDisposable界面,稍后您只是进行Dispose()方法调用,而不是破坏或查杀实际对象

  

什么是非托管资源?

非托管资源是垃圾收集器无法收集的资源。例如,由托管代码之外的其他程序或代码分配的内存。因此GC无法自动管理。