c# - How to Ensure Immutability of a Generic -


this example in c# question applies oo language. i'd create generic, immutable class implements ireadonlylist. additionally, class should have underlying generic ilist unable modified. initially, class written follows:

public class datum<t> : ireadonlylist<t> {     private ilist<t> objects;     public int count      {          get;          private set;     }     public t this[int i]     {                 {             return objects[i];         }         private set         {             this.objects[i] = value;         }     }      public datum(ilist<t> obj)     {         this.objects = obj;         this.count = obj.count;     }      ienumerator ienumerable.getenumerator()     {         return this.getenumerator();     }     public ienumerator<t> getenumerator()     {         return this.objects.getenumerator();     } } 

however, isn't immutable. can tell, changing initial ilist 'obj' changes datum's 'objects'.

static void main(string[] args) {     list<object> list = new list<object>();     list.add("one");     datum<object> datum = new datum<object>(list);     list[0] = "two";     console.writeline(datum[0]); } 

this writes "two" console. point of datum immutability, that's not okay. in order resolve this, i've rewritten constructor of datum:

public datum(ilist<t> obj) {     this.objects = new list<t>();     foreach(t t in obj)     {         this.objects.add(t);     }     this.count = obj.count; } 

given same test before, "one" appears on console. great. but, if datum contains collection of non-immutable collection , 1 of non-immutable collections modified?

static void main(string[] args) {     list<object> list = new list<object>();     list<list<object>> containinglist = new list<list<object>>();     list.add("one");     containinglist.add(list);     datum<list<object>> d = new datum<list<object>>(containinglist);     list[0] = "two";     console.writeline(d[0][0]); } 

and, expected, "two" printed out on console. so, question is, how make class immutable?

you can't. or rather, don't want to, because ways of doing bad. here few:

1. struct-only

add where t : struct datum<t> class. structs usually immutable, if contains mutable class instances, can still modified (thanks servy). major downside classes out, immutable ones string , immutable class make.

var e = new extraevilstruct(); e.mutable = new mutable { myval = 1 }; datum<extraevilstruct> datum = new datum<extraevilstruct>(new[] { e }); e.mutable.myval = 2; console.writeline(datum[0].mutable.myval); // 2 

2. create interface

create marker interface , implement on immutable types create. major downside built-in types out. , don't know if classes implementing truly immutable.

public interface iimmutable {     // space intentionally left blank, except comment } public class datum<t> : ireadonlylist<t> t : iimmutable 

3. serialize!

if serialize , deserialize objects passed (e.g. json.net), can create completely-separate copies of them. upside: works many built-in , custom types might want put here. downside: requires time , memory create read-only list, , requires objects serializable without losing important. expect links objects outside of list destroyed.

public datum(ilist<t> obj) {     this.objects =       jsonconvert.deserializeobject<ilist<t>>(jsonconvert.serializeobject(obj));     this.count = obj.count; } 

i suggest document datum<t> class should used store immutable types. sort of unenforced implicit requirement exists in other types (e.g. dictionary expects tkey implements gethashcode , equals in expected way, including immutability), because it's difficult not way.


Comments

Popular posts from this blog

python - mat is not a numerical tuple : openCV error -

c# - MSAA finds controls UI Automation doesn't -

wordpress - .htaccess: RewriteRule: bad flag delimiters -