I was reading some of the documentation on MSDN concerning do’s and don’t with regards to whether something should be implemented as a property or as a method. I ran into one rule in particular that I have a question about.
If “The operation returns an array” use a method (instead of a property).
The page is here: Choosing Between Properties and Methods
Use a method where the operation returns an
array because to preserve the internal array, you would have to return
a deep copy of the array, not a reference to the array used by the
property. This fact, combined with the fact that developers use
properties as though they were fields, can lead to very inefficient
code.
I understand that the get method of the property would return a reference to the array, which would allow the array to be changed even if there is no set. In the example they give, they are making a deep copy of the array every time the property is accessed, I guess to avoid the possibility of this happening, and this in turn is very inefficient.
It would not be inefficient if the property just returned the reference, and didn’t do all the copying, right? And also using a method instead of a property is not going to automatically protect the list from being modified. It is pretty much the same scenario, you would still need a deep copy.
Is using a property and just returning the reference to the array always bad practice? What if you want the caller to be able to modify the array, or you do not care if they modify it? Is it still bad and why, and if so what would be the proper way to allow the caller to modify?
Can you allow the caller to modify an internal array through a property? Yes, of course, but you will take on a slew of possible issues. How you handle those issues and what you can live with is up to you.
The MSDN advice is correct in a very strict sense. That said I have seen
List<T>andT[]properties returned before from classes. If your class is a very simple POCO, this is not a big issue because then those classes are just raw data and there’s no real business logic to affect.That said, if I’m returning a list, and I don’t want anyone to mess with the internal list, I either return a deep copy every time, or a
ReadOnlyCollection, or an iterator. For example, there’s lots of places I cache web service request calls, and when i return a cache item, I do NOT want the caller modifying that data or they’ll modify what I’m caching. Thus there I make deep copies (which is still faster than the overhead of the web service call).You just have to know whether your usage requires the safety or not. Is the class only for internal consumption? Or is it designed to be consumed by a wider audience and you have no idea what they are going to do with it? Those type of questions may drive your response.
Sorry for a “it depends” answer, but it truly does depend on what your goal is and if the internals of the class are sensitive to change.
UPDATE You can also return an iterator, I’d avoid returning IEnumerable as a superclass up-cast because it can be cast back down, but if you return an iterator instead (like using Skip(0)) you are safe (aside from still being able to modify the contained objects of course).
For example:
Is better than:
Because the later can still be cast back to
List<T>or whatever it was, while the first is an iterator and can’t be modified.