有没有办法确保在IDisposable类的反序列化期间在异常上调用Dispose()?

时间:2009-06-29 07:29:43

标签: c# exception xml-serialization idisposable

在c#中,我使用以下语句反序列化实现IDisposable类型的对象(仅供说明)。

XmlSerializer s = new XmlSerializer(typeof(MyDisposable))
MyDisposable o = (MyDispoable)s.Deserialize(filepath);

afaik,序列化程序尝试使用默认的ctor构造对象,然后分配所有公共属性和字段。如果引发任何异常,我将无法抓住构造的物体。

所以,我的问题是,是否有任何方法可以确保自动释放已分配的资源。我知道Dispose(bool disposing) - 'pattern'实现了一个明确的终结器,但我觉得更明确地释放任何资源(即确定性)。

6 个答案:

答案 0 :(得分:4)

DTO实际上资源要解除分配似乎是不寻常的情况,所以我可以理解它是否在失败时不提供IDisposable支持(我自己的序列化器没有,要么 - 所以我当然不能批评。)

也许更改你的类,这样如果它 有资源要处理,它会懒惰地获取这些资源(即不仅仅是在反序列化类型时)。

XmlSerializer不支持回调,否则最终的回调将是一个急切加载资源的可能选项(虽然有点hacky)。

答案 1 :(得分:1)

您使用using子句确定性地释放资源:

using (MyDisposible o = (MyDisposible)s.Deserialize (filepath))
{
 // Do stuff with 0
}

我会问你为什么要这样做。在C#中,如果它们与SQL连接或文件等外部物理资源相关联,您只需要确定性地释放它们。

垃圾收集器比手动内存管理渐进地更有效,并且允许内存引用超出范围以便被释放是一种很好的做法。

答案 2 :(得分:0)

你的默认构造函数是否做了需要处理的东西?如果是,这是一个好主意(特别是对于要在xml中序列化的对象)?如果不是,那你为什么担心呢?把它留给垃圾收集器......

[编辑:删除关于公共字段的点,因为它不正确]
我也将这个答案留给它可能具有的任何教育价值 - >阅读Marc的评论

答案 3 :(得分:0)

如果在XmlSerializer.Deserialize方法中引发任何异常,它将传播到下一个catch方法,并且不会分配您的对象(o)。因此,除非您使用属性设置器在反序列化期间分配一些非托管资源,否则我不明白为什么您应该关注手动处理对象。

但是如果您的类确实分配了非托管资源,那么正确实现IDisposable意味着您还将从对象的终结器中释放非托管资源,这样就足够了。没有其他方法可以在首先未分配的对象上调用Dispose()

话虽如此,我必须管理员,如果xml文件在反序列化期间没有完全有效,我有几次XmlSerializer会挂起 - 所以我在反序列化之前最终做了模式验证,只是为了确保一切正常。

答案 4 :(得分:0)

获取异常后如何调用GC.Collect(0,GCCollectionMode.Forced)?

答案 5 :(得分:0)

Disposer和Finalizer在C#中不是一回事。

一个处理程序实现一个调用来显式处理你使用的资源,而不是它们中的内存。您的对象的用户需要调用它。

您可以在C#中使用终结器,以确保即使您的处理器未被调用,您仍然不会泄漏资源。即.Net保证在实际垃圾收集之前尝试运行你的处理器。

如果调用中有异常,XmlSerializer负责调用它不会泄漏内存。如果发生这种情况,那么您将在.Net中发现一个错误并随时报告。如果你调用deserialize并抛出一个异常,你就不会把对象拿回来,它已经消失......

.Net的垃圾收集器顺便说一句,它是您使用托管语言获得的免费赠品之一,因为您不必担心清理内存(在大多数情况下),这样您就可以更专注于什么你的代码正在做,并做到了。