我有一个通用类,让我们称之为“观察者”。
public static class Observer<T>
{
public static Action<T> Trigger = (x) => { };
}
因此,无论何时我想使用此功能,我都可以致电:
Observer<Player>.Trigger += OnPlayerChange;
Observer<Player>.Trigger(p);
问题是我无法删除“玩家”的Observer通用实例。因此它的记忆依然存在。我可以清除这些值,但它们的默认值仍然存在。
有没有一种方法可以删除引用?
答案 0 :(得分:2)
Observer<Player>
是一种类型,而不是对象实例。引用该类型后,将立即执行静态构造函数和初始化程序,并将该类型加载到AppDomain中。据我所知,卸载类型的唯一方法是卸载整个AppDomain。就是说,我认为加载的类型本身并不会占用大量内存,并且管理AppDomains非常麻烦,并且几乎可以肯定,仅卸载类型是不值得的。通常,它们用于管理需要动态加载或卸载的整个程序集,或用于完全隔离同一进程中的执行代码。但是,如果您确实需要卸载类型,则该选项确实存在。如果您确实想走那条路线,请参见https://docs.microsoft.com/en-us/dotnet/framework/app-domains/,了解更多详情
但是,我建议您弄清楚为什么加载类型会导致问题以及如何以其他方式管理它。例如,如果您真正的问题是Observer具有一个静态成员,该成员保留了大量引用和固定的数据,则可以手动释放它:
public static class Observer<T>
{
public static Action<T> Trigger = (x) => {
referenceToALotOfMemory = new byte[100000];
};
private static byte[] referenceToALotOfMemory;
public static void IAmDoneWithThisType() {
referenceToALotOfMemroy = null;
}
}
Observer<Player>.Trigger += OnPlayerChange;
Observer<Player>.Trigger(p);
Observer<Player>.Trigger -= OnPlayerChange;
Observer<Player>.IAmDoneWithThisType();
如果您进行任何类型的多线程处理,这当然会充满许多并发问题,并且具有非常糟糕的“代码气味”。只需将其转换为非静态实例,将会更加容易,安全和易读:
public class Observer<T>
{
public Action<T> Trigger = (x) => {
referenceToALotOfMemory = new byte[100000];
};
private byte[] referenceToALotOfMemory
}
var observer = new Observer<Player>();
observer += OnPlayerChange;
observer.Trigger(p);
observer -= OnPlayerChange;
//let the garbage collector cleanup referenceToALotOfMemory when the time is right