Reputation: 1994
I'm writing a Singleton class for access to a List. When the Singleton is first initialized this List is populated by de-serializing an xml file.
This all works great but I want this List to be updatable and in order to do so I'm currently having to re-serialize each time I add or remove from it.
I would prefer to simply have one call to serialize the list when the object is removed from memory. However I feel that trying to do this in the ~Destructor can potentially cause lost data etc.
What is the best pattern to follow to achieve this behavior?
Thanks
Upvotes: 1
Views: 145
Reputation: 10401
Destructors in C# are very different from C++ destructors. They are not actual destructors that are run on fully correct objects which are no longer required, but a last resort measure to deal with unmanaged resources (MSDN):
You should override Finalize for a class that uses unmanaged resources such as file handles or database connections that must be released when the managed object that uses them is discarded during garbage collection.
So it is a bad idea to use Finalizer (Destructor) to interoperate with managed resources, because:
The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already been finalized when the finalizer of Object A starts.
Deserialized data list may be correct during such finalization, or it may have been already reclaimed during previous GC runs. Even if it is not so with current garbage collector, no one can guarantee that such problem won't appear in the next .NET version. Accessing managed resources in Finalizer's is practically an undefined behaviour.
Possible solution
Taking into account that your object is singleton, and thus it can be garbage collected only when application exits (or never if it is never requested), the simplest way to allow such persistent storage to object's data is to attach event handler to the application close(exit) event.
...
public static Singleton Instance
{
get
{
if (_Instance == null)
{
_Instance = new Singleton();
Application.Exit += (sender, args) =>
{
_Instance.SaveChanges();
}
}
return _Instance;
}
}
Or use appropriate Lazy<T>
constructor if your Singleton is based on its use.
Upvotes: 2