If you're using a modern .NET version, one approach is to return a ReadOnlyCollection<T>
object--this is a wrapper around your collection that will throw exceptions if you try to modify it. List<T>.AsReadOnly()
creates this wrapper. But it's not statically typesafe--it won't prevent you from writing bad code. It definitely won't prevent someone from modifying the elements themselves: roList[3].name = "foo";
Another approach is to copy the list. This is safe, works in older .NET versions, but has overhead. When elements are inserted, the new list will be modified. Since it's not a deep copy, elements can be be changed just as in the previous example.
A third possibility is to cast the object to IEnumerable<T>
before returning it, which does not have a list accessor API at all. You can still loop over the elements with foreach
. This will actually prevent you from writing the illegal code, unless the object is cast back to List<T>
. It will make the code that uses the list a little slower and less convenient to write, as the API is more limited than List<T>
.
None of these approaches use a deep copy, which would be the only really safe way to prevent object modification. Since deep copy isn't possible for many types of objects, it's not a viable solution.