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
Post a Comment