我正在尝试序列化Hashset,但我没有运气。每当我尝试打开序列化数据时,我都会得到一个空的HashSet。但是,List工作正常。示例代码:
[Serializable()]
public class MyClass : ISerializable
{
public MyClass(SerializationInfo info, StreamingContext ctxt)
{
HashSet<string> hashset = (HashSet<string>)info.GetValue("hashset", typeof(HashSet<string>));
List<string> list = (List<string>)info.GetValue("list", typeof(List<string>));
Console.WriteLine("Printing Hashset:");
foreach (string line in hashset)
{
Console.WriteLine(line);
}
Console.WriteLine("Printing List:");
foreach (string line in list)
{
Console.WriteLine(line);
}
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
HashSet<string> hashset = new HashSet<string>();
hashset.Add("One");
hashset.Add("Two");
hashset.Add("Three");
info.AddValue("hashset", hashset);
List<string> list = new List<string>();
list.Add("One");
list.Add("Two");
list.Add("Three");
info.AddValue("list", list);
}
}
运行时打印出来:
Printing Hashset:
Printing List:
One
Two
Three
因此List工作正常,但HashSet返回空。有点卡住 - 谁能看到我做错了什么?感谢
答案 0 :(得分:3)
<强>更新强>:
作为 Hans Passant stated,有一个简单的解决方法,只需手动调用HashSet.OnDeserialization。
var hashset = (HashSet<string>)info.GetValue("hashset", typeof(HashSet<string>));
hashset.OnDeserialization(this);
它还有助于其他通用集合。
据我所知,这可能是HashSet<T>
实施中的错误。 HashSet
已正确序列化为SerializationInfo
:
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
info.AddValue("Version", this.m_version);
info.AddValue("Comparer", this.m_comparer, typeof(IEqualityComparer<T>));
info.AddValue("Capacity", (this.m_buckets == null) ? 0 : this.m_buckets.Length);
if (this.m_buckets != null)
{
T[] array = new T[this.m_count];
this.CopyTo(array);
info.AddValue("Elements", array, typeof(T[]));
}
}
和SerializationInfo
已正确恢复。您也可以自己查看,查看:(((System.Collections.Generic.HashSet<string>)(info.m_data[0]))).m_siInfo.m_data[3]
但无法恢复其状态:
它所做的只是存储SerializationInfo
:
protected HashSet(SerializationInfo info, StreamingContext context)
{
this.m_siInfo = info;
}
您可以检查(hashset).m_siInfo.MemberValues[3]
,格式化程序已正确恢复了值,但HashSet
未对其进行“解释”。
类似的问题有Dictionary<TKey,TValue>
或者例如LinkedList<T>
。
List<T>
(或类似的基于数组的集合,例如Stack<T>
)没有问题,因为它们被序列化为数组(没有特殊逻辑)。
解决方法由Hans Passant发布。
恕我直言,BinaryFormatter
并不是存储价值的好方法。您可以尝试使用DataContractSerializer(它可以处理此类类型)或使用序列化帮助程序,如protobuf.net,json.net等。请参阅Why is binary serialization faster than xml serialization?和Performance Tests of Serializations used by WCF Bindings
答案 1 :(得分:2)
区别在于HashSet&lt;&gt;实现ISerializable,List&lt;&gt;没有。解决方法是显式调用它的OnDeserialization()方法,虽然我不确定这是否正确。
var hashset = (HashSet<string>)info.GetValue("hashset", typeof(HashSet<string>));
hashset.OnDeserialization(this);
var list = (List<string>)info.GetValue("list", typeof(List<string>));
// etc..