我正在编写Singleton类来访问List。首次初始化Singleton时,将通过反序列化xml文件来填充此List。
这一切都很好但我希望这个List可以更新,为了做到这一点,我每次添加或删除时都要重新序列化。
当从内存中删除对象时,我宁愿只调用一次序列化列表。但是我觉得在~Destructor中尝试这样做可能会导致数据丢失等。
实现此行为的最佳模式是什么?
由于
答案 0 :(得分:2)
来自C ++析构函数的C#are very different中的析构函数。它们不是在不再需要的完全正确的对象上运行的实际析构函数,而是处理非托管资源的最后手段(MSDN):
您应该为使用非托管资源的类重写Finalize 例如必须释放的文件句柄或数据库连接 当在垃圾中丢弃使用它们的托管对象时 集合。
因此,使用Finalizer (Destructor)与托管资源进行互操作是一个坏主意,因为:
两个对象的终结器不能保证在任何对象中运行 特定顺序,即使一个对象引用另一个对象。也就是说,如果 对象A具有对象B的引用,并且都具有终结符Object 在对象A的终结器时,B可能已经完成 启动。
反序列化数据列表在此类最终确定期间可能是正确的,或者在之前的GC运行期间可能已经回收。即使现在的垃圾收集器不是这样,也没有人能保证这个问题不会出现在下一个.NET版本中。在Finalizer中访问托管资源实际上是一种未定义的行为。
可能的解决方案
考虑到你的对象是单例,因此只有在应用程序退出时才会被垃圾收集(或者永远不会被请求), 允许此类持久存储对象数据的最简单方法是将事件处理程序附加到application close(exit) event。
...
public static Singleton Instance
{
get
{
if (_Instance == null)
{
_Instance = new Singleton();
Application.Exit += (sender, args) =>
{
_Instance.SaveChanges();
}
}
return _Instance;
}
}
如果您的Singleton基于其使用,则使用适当的Lazy<T>
constructor。