为什么C#中的Counter(带CRTP)没有';对于某些类型的对象,不要倒计时
本文关键字:类型 于某些 对象 倒计时 Counter 中的 CRTP 没有 为什么 | 更新日期: 2023-09-27 18:21:28
我已经在C#计数器中使用CRTP实现了,但我不知道为什么它对某些类型不倒计数:
using System;
using Type1 = C<char>;
using Type2 = C<int>;
class ExistingObjectCounter<CountedType>
{
private static uint existingObjects = 0;
protected ExistingObjectCounter()
{
++existingObjects;
}
~ExistingObjectCounter()
{
Console.WriteLine("Destruction of " + this + " number " + existingObjects);
--existingObjects;
}
public static uint GetNumberOfLivingObjects
{
get
{
return existingObjects;
}
}
}
class C<T> : ExistingObjectCounter<C<T>>
{
public C()
{}
public C(C<T> m)
{}
};
class ZliczaczObiektow
{
public static void createManyCClassWithStringArgument()
{
for(int i=0; i<10;++i)
new C<String>();
}
public static void Main()
{
Type1 c1 = new Type1(), c2 = new Type1(), c3 = new Type1(c2);
var ws1 = new Type2();
Console.WriteLine("existing objects of class " + c1.GetType() + ": "
+ Type1.GetNumberOfLivingObjects);
Console.WriteLine("existing objects of class " + ws1.GetType() + ": "
+ Type2.GetNumberOfLivingObjects);
createManyCClassWithStringArgument();
{
Type1 c4 = new Type1(), c5 = new Type1();
var ws2 = new Type2();
Console.WriteLine("existing objects of class " + c4.GetType() + ": "
+ Type1.GetNumberOfLivingObjects);
Console.WriteLine("existing objects of class " + ws2.GetType() + ": "
+ Type2.GetNumberOfLivingObjects);
createManyCClassWithStringArgument();
}
System.GC.Collect();
Console.WriteLine("existing objects of class " + c1.GetType() + ": "
+ Type1.GetNumberOfLivingObjects);
Console.WriteLine("existing objects of class " + ws1.GetType() + ": "
+ Type2.GetNumberOfLivingObjects);
Console.WriteLine("existing objects of class C<String>: "
+ C<String>.GetNumberOfLivingObjects);
Console.ReadKey();
}
}
输出为:
existing objects of class C`1[System.Char]: 3
existing objects of class C`1[System.Int32]: 1
existing objects of class C`1[System.Char]: 5
existing objects of class C`1[System.Int32]: 2
existing objects of class C`1[System.Char]: 5
existing objects of class C`1[System.Int32]: 2
existing objects of class C<String>: 20
Destruction of C`1[System.String] number 20
Destruction of C`1[System.String] number 19
Destruction of C`1[System.String] number 18
Destruction of C`1[System.String] number 17
Destruction of C`1[System.String] number 16
Destruction of C`1[System.String] number 15
Destruction of C`1[System.String] number 14
Destruction of C`1[System.String] number 13
Destruction of C`1[System.String] number 12
Destruction of C`1[System.String] number 11
Destruction of C`1[System.String] number 10
Destruction of C`1[System.String] number 9
Destruction of C`1[System.String] number 8
Destruction of C`1[System.String] number 7
Destruction of C`1[System.String] number 6
Destruction of C`1[System.String] number 5
Destruction of C`1[System.String] number 4
Destruction of C`1[System.String] number 3
Destruction of C`1[System.String] number 2
Destruction of C`1[System.String] number 1
编辑:我的问题是,为什么计数器在某些情况下不会下降,但在另一种情况下会下降?为什么Type1和Type2在程序结束时没有调用析构函数,但另一方面,用String参数化的C却调用了析构函数
您不能依赖任何垃圾收集器行为。如果需要析构函数类型的行为,那么让类继承IDispose并手动调用Dispose()。
Mark Feldman的回答和建议非常切中要害,通常应该做什么而不是依赖垃圾收集器(因为GC太不可靠了,即使在明确调用时也无法启动)。
但对于你的问题:你的主要问题归结为垃圾收集器。即使被调用,也不能保证它会从内存中删除所有不再使用(引用)的变量(对于需要与其他任何东西完全不同地处理的图像,情况更糟)。因此,您所看到的是GC在做它的工作,但并不像您所期望的那样。
这是你两个问题的唯一原因:为什么有些对象计数下降,而另一些对象计数没有下降(即使没有被引用)。
不过,你可以尝试的一件事是,在你调用GC.Collect();
之后,你也会调用GC.WaitForPendingFinalizers();
。这可能会有所帮助,但遗憾的是,垃圾收集器并不能100%保证它会有所帮助。
因此,如果你没有绝对必要使用垃圾收集器(绝对是:如果你没有消除程序因此崩溃的不常用变量,你会占用太多内存),那么你应该避免使用它,例如Mark Feldman在他的回答中描述的方法。