使用SerializationInfo的AddValue处理添加的对象

时间:2010-09-13 14:23:50

标签: c# memory serialization memory-management

如何确保将对象添加到SerializationInfo对象中?

例如:如果我在信息对象中添加一个哈希表,我如何确保在序列化之后,我的类的hastable对象没有活着的引用,我可以以某种方式释放内存?

info.AddValue("attributesHash", attributesHash, typeof(System.Collections.Hashtable));


更新(代码)

[Serializable]
class A : System.Runtime.Serialization.ISerializable
{
    List<int> m_Data = new List<int>();
    //...
    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
    {
        if (m_Data != null)
        {
            info.AddValue("MyData", m_Data, typeof(List<int>));
            m_Data.Clear();
        }
        m_Data = null; // <-- Will this be collected by GC?
        GC.GetTotalMemory(true); //forced collection
    }
};

我的问题是:如果我在添加到信息列表后使我的对象为null,它将在调用序列化后释放(当信息被销毁时 - 我希望),或者在调用GC的函数时(在我的行中)不这么认为)?

如果设置'm_Data = null'不会将其标记为垃圾,那么我怎么知道m_Data占用的内存是否已被释放?

3 个答案:

答案 0 :(得分:2)

“我可以以某种方式释放记忆”而“物品被处置”并不顺利。

内存管理由GC完成。只要没有对象的引用,它就会被标记为垃圾收集。因此它处理托管资源。

然而,处置是完全不同的动物,并且在实现IDisposable的类型上调用Dispose()并处理非托管资源,例如文件句柄和窗口资源。

你需要明确你的意思。

答案 1 :(得分:0)

您需要使您的包含对象实现IDisposable。但仅仅因为你已经被序列化并不意味着你也需要被处置。然后,引用对象应该在序列化后调用dispose,如果这是预期的那样。

对于反序列化的对象,它也应该在它被使用时通过它的任何引用来处理(可能在另一个appdomain中?)。所以这意味着两个实例都需要处理。如果您共享的资源是单个实例(例如IntPtr),那么您可能需要更加聪明,例如不使用此对象处理该非托管资源,而是从更高级别处置。

一般经验法则:创造它的人,处理它。

IDisposable documentation所描述的另一种常见模式是将Dispose()调用到对象析构函数中。这将为您提供非确定性的处理时间,但保证可以正常工作(假设您没有参考泄漏)。

答案 2 :(得分:0)

经过大量分析后,我不认为GC会在请求时收集内存...至少在GetTotalMemory函数的情况下不会。

将对象设置为null会将其标记为垃圾,但这并不意味着它会立即收集。