在c#中,我使用以下语句反序列化实现IDisposable类型的对象(仅供说明)。
XmlSerializer s = new XmlSerializer(typeof(MyDisposable))
MyDisposable o = (MyDispoable)s.Deserialize(filepath);
afaik,序列化程序尝试使用默认的ctor构造对象,然后分配所有公共属性和字段。如果引发任何异常,我将无法抓住构造的物体。
所以,我的问题是,是否有任何方法可以确保自动释放已分配的资源。我知道Dispose(bool disposing) - 'pattern'实现了一个明确的终结器,但我觉得更明确地释放任何资源(即确定性)。
答案 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的垃圾收集器顺便说一句,它是您使用托管语言获得的免费赠品之一,因为您不必担心清理内存(在大多数情况下),这样您就可以更专注于什么你的代码正在做,并做到了。