【问题标题】:Disposing Objects in C#在 C# 中处理对象
【发布时间】:2017-10-29 13:28:36
【问题描述】:

我有以下情况。我继承了子类,想知道子类消失后超类会发生什么

以下是我的实现:

class Program
{
    static void Main(string[] args)
    {
        using (var a = new SuperHuman())
        {

        }

        Console.ReadLine();
    }
}

class Human : IDisposable
{
    public string LoType = "Normal";

    public Human()
    {
        Console.WriteLine("Human Created");   
    }

    public string GetHumanType()
    {
        return LoType;
    }

    public void Dispose()
    {            
        Console.WriteLine("{0} Human Class gONE", LoType);            
    }
}

class SuperHuman : Human
{                
    public SuperHuman()           
    {
        LoType = "Super";
        Console.WriteLine("{0} Human Created",LoType);   

    }

}

给我以下输出:

Human Created
SuperHuman Created
SuperHuman Class Gone

我想知道的是 Parent 类是否也消失了 如果不是,我如何将它与子类一起处理?

【问题讨论】:

  • 你不会处理一个 class,你会处理一个 object - 当你创建一个SuperHuman 的实例时,你'实际上并没有创建两个对象……您只是在创建一个。所以是的,您的对象已被处置。
  • 附带说明:可以说,这个测试输出实际上并不是显示创建和处理,而是调用了哪些方法。 Superhuman 构造函数隐式调用 Human 构造函数(不显示 LoType)。如果基类实现了一个以 LoType 作为参数(或抽象属性)的构造函数,并且输出将显示该类型,那么您也只会看到超人类的“创建”。 Dispose 仅​​显示包含 lotype 的输出,并且不会在继承类中被覆盖

标签: c# garbage-collection dispose


【解决方案1】:

你的问题

首先,对于类和对象之间的区别似乎有些混淆。

使用new-关键字,SuperHuman 的新实例被实例化。

using (var a = new SuperHuman())
{
    // inside this block, "a" contains a reference to a SuperHuman-Object, 
    // which is also a Human-Object and thus can be Disposed. 
    // (As it implements IDisposable and must have a Dispose-Method)
}

所以基本上你的课程根本没有发生任何事情using 块最后在 Object 上调用 Dispose()-Method。所以无论你在里面做什么,这个方法都在做。

IDisposable-接口

这里就不详细解释了。

这是来自MSDN的接口描述

提供释放非托管资源的机制。

这意味着,如果您定义一个 Human 实现IDisposable,则所有非托管资源(例如数据库连接)将在调用Dispose()-方法时被释放。所以有责任在你的代码中释放这些资源。然而,Human 仍然是一个托管资源。但这与IDisposable 没有任何关系,因为托管资源 正在由Garbage Collection 完成,当一个对象 没有被使用时,它会自动检测没有了。

但究竟什么是非托管资源

这已经回答here

还释放托管资源?

即使该接口不打算这样做,您也可以通过将值设置为 null 来释放托管资源。另一个Thread 也已经回答了这是如何工作的。

【讨论】:

  • 如果 Human 和 Super Human 类没有父子关系,而是我在 SuperHuman 类中创建 Human 的新实例然后使用 using 语句,即使在括号末尾 SuperHuman 类将消失,超人类内部初始化的对Human类的引用呢?
  • 如果类A处理非托管资源,它应该实现IDisposable。然后B 类可以在using-Block 内本地使用A 并隐式调用Dispose() 包含(关联)A 的实例及其自身实现IDisposable 并在自己的Dispose()-Method 中调用A-child 的Dispose()-Method。
【解决方案2】:

为了清楚起见,实例并没有在您处置后消失。它已释放所有非托管资源,可以在此之后免费释放,以便垃圾收集器可以拾取它。

在您的示例代码中,只有一个实例(派生类及其基类没有两个实例)。您无法从内存中删除半个实例。它存在或消失。

using 块结束后,派生类的实例将免费提供给垃圾收集器(不是因为using,但它离开了范围)。在适当的时候,垃圾收集器会释放内存。

【讨论】:

    猜你喜欢
    • 2011-09-12
    • 2011-04-26
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    相关资源
    最近更新 更多