c# - Serializing a HashSet -
i'm trying serialize hashset i'm having no luck. whenever try open serialized data, empty hashset. however, list works fine. example code:
[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); } } and when run, prints out:
printing hashset: printing list: 1 2 3 so list works fine, hashset comes empty. little stuck - can see i'm doing wrong? thanks
update:
as hans passant stated there simple workaround, call hashset.ondeserialization manually.
var hashset = (hashset<string>)info.getvalue("hashset", typeof(hashset<string>)); hashset.ondeserialization(this); it helps other generic collections.
as far can see bug in hashset<t> implementation. hashset correctly serialized 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[])); } } and serializationinfo correctly restored. can check yourself, take to: (((system.collections.generic.hashset<string>)(info.m_data[0]))).m_siinfo.m_data[3] fails restore state:
all stores serializationinfo:
protected hashset(serializationinfo info, streamingcontext context) { this.m_siinfo = info; } you can check (hashset).m_siinfo.membervalues[3], values correcly restored formatter not "interpreted" hashset.
similar problem has dictionary<tkey,tvalue> or e.g. linkedlist<t>.
list<t> (or similar array based collections such stack<t>) has no problem since serialized array (without special logic).
workaround posted hans passant.
imho, binaryformatter not , efficient way store values. can try use datacontractserializer (it can handle such types) or go serialization helpers such protobuf.net, json.net etc. see why binary serialization faster xml serialization? , performance tests of serializations used wcf bindings
Comments
Post a Comment