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