我正在尝试创建一个简单的类,它在不再使用时将自身序列化为磁盘。我现在的代码(见下文)。我现在的代码似乎有效,但我对自己的知识并不完全自信,所以我想知道是否有其他人发现此代码存在任何重大问题。
void IDisposable.Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MyClass()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, this);
byte[] output = Dostuff(ms);
File.WriteAllBytes(DBPATH, output);
}
this.disposed = true;
}
答案 0 :(得分:6)
这可能会奏效 - 但我不会这样做。通过这样做,您可能会在终结线程中执行潜在危险的代码。如果出现任何问题,你的状况会很糟糕......
处理应该除了处理您的资源之外什么都不做。我强烈建议将其移至另一个方法,并使其成为对象API的一部分,而不是依赖IDisposable来处理您的处理。
答案 1 :(得分:5)
几乎不可能正确地编写终结器,而在一个中完成这种工作只是一个灾难的处方。更不用说它会破坏性能并且无法调试。终结者的规则1是不要使用它们。规则2(仅限高级用户)不使用它们,除非您确定必须这样做。
如果只是为了一个有趣的爱好项目,那么没有真正的伤害,它可能会运作得很好,但如果我在生产代码库中看到过类似的东西,我会哭。
如果你确实想做这样的事情,那么我会把它作为一个显式调用,并且只是在调试期间使用终结器来捕获未调用显式方法的情况,例如。
class MyClass
{
private bool dirty; // set this whenever the object changes
~MyClass
{
if (this.dirty)
{
Debug.Fail("Object was not saved.");
}
}
public void Save()
{
if (this.dirty)
{
// TODO: do the save
this.dirty = false;
}
}
}
答案 2 :(得分:4)
首先,我认为你的设计相当薄弱,因为你的班级违反了Single Responsibility Principle。更为可取的是区分两个职责:可序列化实体以及将此实体保存/读取到持久存储/从持久存储中读取。在大多数情况下,可序列化的实体是lightwait,而finalizable类则不是。
其次,你应该避免在终结器中使用复杂的逻辑。例如,将可序列化类保存到Storage.Dispose方法的持久存储中会更好。并且从终结器方法只将警告写入日志文件,因为它显示不适当的类存储使用情况:
[Serializable]
public class MySerializableClass {
}
public sealed class MyStorage : IDisposable {
~MyStorage()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
//We can access to all managed resources
using (var ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, mySerializableClass);
byte[] output = Dostuff(ms);
File.WriteAllBytes(DBPATH, output);
}
}
else
{
//Inappropriate storage usage!
//We can't guarantee that mySerializableClass object would
//properly saved to persistant storage.
//Write warning to log-file. We should fix our code
//and add appropriate usage!
}
}
this.disposed = true;
}
}