我在学校简要介绍了类之间的关系(UML),我希望用代码展示组合和聚合在实际使用中的工作原理以及它们之间的区别。为了做到这一点,我希望能够能够看到所有活动对象atm,以证明我删除的对象和它所属的对象现在真的消失了。
这是我想要做的一个简单示例:
List<Company>companies = new List<Company>(){
new Company(){
Name = "Greiner",
new Boss(){
Name = "Hugo",
},
},
};
Company comp = companies.FirstOrDefault();
companies.Remove(comp);
现在我想以某种方式表明Boss与公司一起消失,而不仅仅是对他的(间接)引用。所以我想到了所有活动对象。
有没有办法做到这一点?我知道垃圾收集器应该这样做,但我不想告诉我的同学们只相信我的话。
我也倾向于认为过于复杂,所以我的方法可能完全倒退,所以欢迎任何建议如何证明聚合和组合之间的差异。
此致
Andreas Postolache
答案 0 :(得分:1)
你可以在你的班级中保留一个静态计数器来记录号码。创建的实例。在构造函数中递增此计数器并在析构函数中减少它。课程结构样本如下所示。
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--;
}
}
现在你可以看到没有。在任何需要的地方打印此计数器的实例。
您现在可以实例化您的班级公司并检查对象的数量。
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;
输出结果应为公司:1和Boss:1
现在在按钮上单击编写以下代码
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Company: " + Company.counter.ToString());
Console.WriteLine("Boss: " + Boss.counter.ToString());
请注意,您必须调用垃圾收集方法以强制立即收集,否则您无法保证GC何时移除该对象。
公司和老板的输出现在都显示为0。
注意:仅在课堂上使用GC.Collect进行演示。
答案 1 :(得分:1)
垃圾收集在这里让你感到困惑 - 也许在本机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不会收集该项。看起来有一个来自当前范围的隐式引用,它使对象保持活动状态。这就是我将项目创建推送到单独功能的原因。