A property which encapsulates part of an object's mutable state may, if the type is a mutable class, represent any of these:
- A live mutable view of the property's state
- A mutable view of a detached copy of the property's state
- A mutable view of a state that may or may not remain attached to the property's state
If the type is read-only, but not guaranteed to be immutable, it may represent any of these:
- A guaranteed-"live" read-only view of the property's state
- An immutable copy of the state as of the time it was called
- A view of a state that may start out being attached to the property's state, but may or may not remain attached.
While the type of the determined object may be used to distinguish the first set of three behaviors from the latter set, I know of no standard convention to indicate, in the absence of a suitable guaranteed-immutable return type, which of the behaviors within the appropriate set applies. Since there is no guaranteed-immutable implementation of IEnumerable<T>
that would seem applicable here, your best bet is probably to use Joe's code, but also document your behavior as #3. Unless you can think of some reason clients would benefit from #2, documenting your behavior as #3 will give you the most flexibility to change your implementation in future should that be necessary. For example, if thread-safe access ends up being necessary in the future, your class could implement an internal method which locks the collection long enough to copy it to an array and returns that array (possibly wrapped in ReadOnlyCollection<T>
, though it probably wouldn't matter) cast as IEnumerable<T>
. Such an approach wouldn't work if the property was supposed to represent a live view.