在部署时将类保存到磁盘:我的代码是否有错误?

我正在尝试创建一个简单的类,当它不再使用时将其自身序列化为磁盘。 我现在的代码(见下文)。 我现在的代码似乎工作,但我对我的知识并不完全自信,所以我想知道是否有其他人看到这个代码有任何重大问题。

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; } 

几乎不可能正确地编写终结器,而在一个中完成这种工作只是一个灾难的处方。 更不用说它会破坏性能并且无法调试。 终结者的规则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; } } } 

这可能会奏效 – 但我不会这样做。 通过这样做,您可能在终结线程中执行潜在危险的代码。 如果出现任何问题,你的状况会很糟糕……

处置应该只是处理你的资源。 我强烈建议将其移至另一个方法,并使其成为对象API的一部分,而不是依赖IDisposable来处理您的处理。

首先,我认为你的设计相当薄弱,因为你的class级违反了单一责任原则 。 更为可取的是区分两个职责:可序列化实体以及将此实体保存/读取到持久存储中/从中保存/读取此实 在大多数情况下,可序列化实体是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; } }