如何查看 class 的所有实例?

How can I see all instances of a class?

我在学校有一个关于 类 (UML) 之间关系的简短演示,我想用代码展示组合和聚合在实际使用中的工作原理以及它们之间的区别。然而,为了做到这一点,我希望能够看到所有活动对象 atm,以证明我删除的对象和属于它的对象现在真的消失了。

这是我正在尝试做的一个简单示例:

List<Company>companies = new List<Company>(){ 
    new Company(){ 
      Name = "Greiner", 
      new Boss(){
        Name = "Hugo",
      },
   }, 
};

Company comp = companies.FirstOrDefault();
companies.Remove(comp);

现在我想以某种方式表明老板和公司一起走了,而不仅仅是(间接)提及他。所以我想到了查看所有活动对象。

有什么办法吗?我知道垃圾收集器应该这样做,但我不想告诉我的同学们只相信我的话。

另外我确实倾向于认为过于复杂,所以我的方法可能完全倒退,所以欢迎任何关于如何证明聚合和组合之间差异的建议。

此致

安德烈亚斯·波斯托拉奇

您可以在 classes 中保留一个静态计数器来记录第 1 次。创建的实例。在构造函数中增加此计数器并在析构函数中减少它。 class 结构示例如下所示。

public class Company
{
    public static int counter = 0;
    public Company()
    {
        counter++;
    }
    public string Name {get;set;}
    public Boss Boss { get; set; }
        ~Company()
    {
        counter--;
    }
}

public class Boss
{
    public static int counter = 0;

    public Boss()
    {
        counter++;
    }

    public string Name {get;set;}

    ~Boss()
    {
        counter--;
    }
}

现在你可以看到号码了。通过在需要的地方打印此计数器来减少实例。

您现在可以实例化您的 class 公司并检查对象的数量。

Company company = new Company(){ Name = "Greiner",  Boss = new Boss(){ Name = "Hugo" }} ;

Console.WriteLine("Company: " + Company.counter.ToString());
Console.WriteLine("Boss: " + Boss.counter.ToString());

company = null;

输出结果应该是 Company: 1 and Boss: 1

现在在一个按钮上点击写下下面的代码

GC.Collect();
GC.WaitForPendingFinalizers();

Console.WriteLine("Company: " + Company.counter.ToString());
Console.WriteLine("Boss: " + Boss.counter.ToString());

请注意,您必须调用垃圾回收方法来强制立即回收,否则您无法保证对象何时会被 GC 删除。

Company 和 Boss 的输出现在都显示为 0。

注意:仅在您的 class房间内使用 GC.Collect 进行演示。

这里的垃圾收集使事情变得复杂 - 也许用本机 C++ 来展示它会更有指导意义。但是,您可以显式调用 GC.Collect() 来强制进行垃圾回收。为了能够跟踪对象的删除,可以使用析构函数:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ExampleDeletion
{
    class Program
    {
        public class Company
        {
            public string Name { get; set; }
            public Boss CEO { get; set; }

            ~Company()
            {
                Console.WriteLine("Company destroyed: " + Name);
            }
        }
        public class Boss
        {
            public string Name { get; set; }

            ~Boss()
            {
                Console.WriteLine("Boss destroyed: " + Name);
            }
        }

        static void Main(string[] args)
        {
            List<Company> companies = new List<Company>();

            Add(ref companies);
            Remove(ref companies);

            GC.Collect();

            Console.ReadLine();
        }

        static private void Add(ref List<Company> companies)
        {
            companies.Add(
                new Company()
                {
                    Name = "Greiner",
                    CEO = new Boss()
                    {
                        Name = "Hugo"
                    }
                });
        }

        static private void Remove(ref List<Company> companies)
        {
            Company comp = companies.FirstOrDefault();
            companies.Remove(comp);
        }
    }
}

我在尝试此操作时注意到的一件有趣的事情是,如果您在创建它的同一范围内从列表中删除该项目,则它不会被 GC 收集。看起来有一个来自当前范围的隐式引用使对象保持活动状态。这就是我将项目的创建推到一个单独的函数的原因。