c# - How not to return a mutable from a method and exposing class internals -


i think commonly asked question , believe have covered bases well, in how objects, structs or value types passed between functions. let assume have following classes:

public class user{     public int xcoor{get;set}     public int ycoor{get;set} }  public class usermanager{     dictionary<int,user> usermapping = new  dictionary<int,user>();     public void adduser(user user){//stuff}     public void removeuser(user user){//stuff}     public ienumerable<user> getallusers(){return usermapping.values;} }  public class userconsumer{     private usermanager;     public void getusercoordinates(){         var listthatexposesinternals = usermanager.getallusers().tolist();         listthatexposesinternals.foreach(user => user.xcoor = user.ycoor = 0);     // altered internals of class, messed     // want consumer able read     } } 

how can make sure internals of user class stays intact. aware problem appropriate expose xcoor , ycoor rather whole user class of time face problem (need?) return reference class. appreciate advises.

there number of approaches take. if there never situation xcoor , ycoor should changed after user instantiated, require values in constructor , make setter private ensure can't changed outside class.

public class user {      public user(int xcoor, int ycoor)     {         this.xcoor = xcoor;         this.ycoor = ycoor;     }      public int xcoor{get; private set;}     public int ycoor{get; private set;} } 

if need user mutable, want discourage changing properties under circumstances, create interface user implement has getters on properties. however, people still cast ireadableuser user , access properties.

another option create new class wraps user object, , exposes getters read properties actual user instance, cannot set same properties. option combined ireadableuser approach above, hide implementation details of returned object while still preventing people casting object user change values.

public interface ireadonlyuser {     int xcoor {get;}     int ycoor {get;} }  internal class readonlyuser : ireadonlyuser {     private readonly user user;      public readonlyuser(user user)     {         this.user = user;     }      public int xcoor{get { return this.user.xcoor; }}     public int ycoor{get { return this.user.ycoor; }} }  public ienumerable<ireadonlyuser> getallusers() {     return usermapping.values         .select(u => (ireadonlyuser) new readonlyuser(u)); } 

yet option allow users mutate values return, ensure these values copied values next time asks list of users they're seeing instances haven't been changed.

public ienumerable<user> getallusers() {     return usermapping.values         .select(u => new user { xcoor = u.xcoor, ycoor = u.ycoor }); } 

if had more reference-based values in user class, select statement need create new instances of well. if becomes burdensome, might consider giving each class copy constructor ensure responsibility copying values consolidated part of code it's noticed , fixed when things change.


Comments