2

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

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

afaik,序列化程序尝试使用默认 ctor 构造对象并随后分配所有公共属性和字段。如果出现任何异常,我不会接触到构造的对象。

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

4

6 回答 6

4

DTO 实际上有资源可以释放似乎是不寻常的情况,所以我可以理解它是否不提供IDisposable失败支持(我自己的序列化程序也没有 - 所以我当然不能批评)。

也许改变你的类,以便如果它确实有资源要处理,它会懒惰地占用这些资源(即不仅仅是在反序列化类型时)。

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

于 2009-06-29T07:39:12.193 回答
1

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

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

我会质疑你为什么要这样做。在 C# 中,您只想确定性地释放与外部物理资源(如 SQL 连接或文件)相关联的东西。

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

于 2009-06-29T15:45:10.933 回答
0

得到异常后调用 GC.Collect(0, GCCollectionMode.Forced) 怎么样?

于 2009-06-29T09:54:41.200 回答
0

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

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

话虽如此,我必须管理,如果 xml 文件在反序列化期间不完全有效,我曾有过几次 XmlSerializer 会挂起的情况 - 所以我最终在反序列化之前进行了模式验证,以确保一切正常。

于 2009-06-29T08:22:00.250 回答
0

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

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

于 2009-06-29T07:39:19.540 回答
0

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

处置器实现调用以显式处置您使用的资源,而不是其中的内存。您的对象的用户需要调用它。

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

如果调用中有异常,XmlSerializer 负责在它的调用中不泄漏内存。如果发生这种情况,那么您将在 .Net 中发现一个错误并随时报告它。如果你调用反序列化并且它抛出一个异常,你不会得到对象,它已经消失了......

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

于 2009-07-22T03:42:01.497 回答