I have a class Bar
with a private field containing the reference type Foo
. I would like to expose Foo
in a public property, but I do n
Making a copy, a ReadOnlyCollection
, or having Foo
be immutable are usually the three best routes, as you've already speculated.
I sometimes favor methods instead of properties whenever I'm doing anything more significant than simply returning the underlying field, depending on how much work is involved. Methods imply that something is going on and raise more of a flag for consumers when they're using your API.
"Cloning" the Foo objects you receive and give back out is a normal practice called defensive copying. Unless there is some unseen side-effect to cloning that will be visible to the user, there is absolutely no reason to NOT do this. It is often the only way to protect your classes' internal private data, especially in C# or Java, where the C++ idea of const
is not available. (IE, it must be done in order to properly create truly immutable objects in these two languages.)
Just to clarify, possible side effects would be things like your user (reasonably) expecting that the original object be returned, or some resource being held by Foo that will not be cloned correctly. (In which case, what is it doing implementing IClonable?!)
It sounds like you're after the equivalent of "const" from C++. This doesn't exist in C#. There's no way of indicating that consumers can't modify the properties of an object, but something else can (assuming the mutating members are public, of course).
You could return a clone of the Foo as suggested, or possibly a view onto the Foo, as ReadOnlyCollection does for collections. Of course if you could make Foo
an immutable type, that would make life simpler...
Note that there's a big difference between making the field readonly and making the object itself immutable.
Currently, the type itself could change things in both ways. It could do:
_Foo = new Foo(...);
or
_Foo.SomeProperty = newValue;
If it only needs to be able to do the second, the field could be readonly but you still have the problem of people fetching the property being able to mutate the object. If it only needs to do the first, and actually Foo
is either already immutable or could be made immutable, you can just provide a property which only has the "getter" and you'll be fine.
It's very important that you understand the difference between changing the value of the field (to make it refer to a different instance) and changing the contents of the object that the field refers to.
I was thinking about similar security things. There is probably a way. Quite clear but not short. The general idea is quite simple. However I always found some ways around so never tested it. But you could check it - maybe it will work for you.
This is pseudo code, but I hope idea behind it is clear
public delegate void OnlyRuller(string s1, string s2);
public delegate void RullerCoronation(OnlyRuller d);
class Foo {
private Foo();
public Foo(RullerCoronation followMyOrders) {
followMyOrders(SetMe);
}
private SetMe(string whatToSet, string whitWhatValue) {
//lot of unclear but private code
}
}
So in class which creates this property you have access to SetMe method, but it's still private so except for creator Foo looks unmutable.
Still for anything bigger than few properties this will probably became soon super mess - that's why I always preferred other ways of encapsulation. However if it's super important for you to not allow the client to change Foo, than this is one alternative.
However, as I said, this is only theory.
Unfortunately, there's no easy way around this in C# at the moment. You could extract the "read only part" of Foo
in an interface and let your property return that instead of Foo
.
If you don't want anyone to mess with your state...don't expose it! As others have said, if something needs to view your internal state, provide an immutable representation of it. Alternatively, get clients to tell you to do something (Google for "tell don't ask"), instead of doing it themselves.