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

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

aspxgridview - Devexpress grid - header filter does not work if column is initially hidden -

c# - How to execute a particular part of code asynchronously in a class -