c# - Convenient way to expose dictionary value as base types -


i'm looking see whether there's way expose containers c# classes without revealing unnecessary implementation details. i'm learning c# i'm experienced in other oo languages, know possible it's better expose base classes / interfaces rather concrete types. i'm doing storing collections of key (collection of object) in class. find can expose idictionary(key, collection of object), i'd idictionary(key, ienumerable(object)). simple example make clearer.

class addressbook {     public idictionary<string, list<string>> name2addresses // ok, want idictionary<string, ienumerable<string>>     {         { return name2addresses; }     }      public ienumerable<string> getaddresses(string name)// ok, want convenience of exposing container "one-liner"     {         return name2addresses[name];     }      public addressbook()     {         name2addresses = new dictionary<string,list<string>>();         list<string> addresses = new list<string>(); // i'd prefer ilist<string> addresses = ...         name2addresses.add("anne best", addresses);         addresses.add("home address");         addresses.add("work address");     }     dictionary<string, list<string>> name2addresses; } 

i know exposing container of derived container of base tricky problem in oo because, e.g., add different derived via container base class. because want expose container read-only via ienumerable there might easy way this. code want.

    public idictionary<string, ienumerable<string>> name2addresses     {         { return name2addresses; }     } 

i tried adding cast compiler complained not having one

    public idictionary<string, ienumerable<string>> name2addresses     {         { return (idictionary<string, ienumerable<string>>) name2addresses; }     } 

but got exception:

additional information: unable cast object of type 'system.collections.generic.dictionary2[system.string,system.collections.generic.ilist1[system.string]]' type 'system.collections.generic.idictionary2[system.string,system.collections.generic.ienumerable1[system.string]]'.

any ideas? hoping there might easy / elegant way this, on whole it's been joy move lower-level oo language c# it's quicker , easier put want practise. isn't show-stopper means can reveal list rather ienum , trust myself not abuse list, things have other people using code 1 day.

ps remember reading somewhere c# has improved support sort of thing. i'm on vs2010 if makes difference.

edit

i did searching before asking, after more searching, found has been asked before, in different context, why can't dictionary<t1, list<t2>> cast dictionary<t1, ienumerable<t2>>?. question possibly reduces whether there's way of having read-only idictionary (see is there read-only generic dictionary available in .net?)

another edit

as alex g / code4life suggested, work: without rolling own read-only dictionary class can create new dictionary. e.g.

    public idictionary<string, ienumerable<string>> name2addressesnewdictionary     {                 {             return name2addresses.todictionary(na=>na.key, na=>na.value.asenumerable());         }     } 

this incurs performance penalty every time accessed + space penalty of creating new key-value pairs (and dict itself). plus developer time. doesn't seem better exposing list, in general, if i'm using property (especially work going on under covers). method / in other circumstances.

third edit

as jens kloster suggested, change definition of container use ienumerable value

    dictionary<string, ienumerable<string>> name2addresses; 

and cast when need in implementation.

        ((ilist<string>)name2addresses["anne best"]).add("alternative address"); 

try changing field use ienumerable instead of list.

dictionary<string, ienumerable<string>> name2addresses; 

then should have no problem having property this:

 public idictionary<string, ienumerable<string>> name2addresses  {    { return name2addresses; }  } 

and can still this:

 public addressbook()     {         name2addresses = new dictionary<string,ienumerable<string>>(); //changed ere         list<string> addresses = new list<string>();          name2addresses.add("anne best", addresses);         addresses.add("home address");         addresses.add("work address");     } 

also - have @ this post


Comments

Popular posts from this blog

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -

node.js - Bad Request - node js ajax post -