Question

Say I have:

class foo
{
  private List<T> bar;
  public IEnumerable<T> GetBar();
}

where GetBar() should return that very same List, without exposing internals (i.e. no other class should be able to remove elements from the internal list, reorder it etc.) and avoiding excessive copying. What is the standard way to do this?

Was it helpful?

Solution

If you want to return an immutable list, return bar.AsReadOnly().

Typically the member that exposes this readonly wrapper would be of type IList<T>. I would only downcast to IEnumerable<T> if I wanted to indicate to the consumer that the implementation might use lazy enumeration.

Personally I'd make it a property, and return the same readonly wrapper on each invocation:

class Foo
{
    private List<T> bar;
    private IList<T> readonlyBar;

    public Foo()
    {
        bar = ...;
        readonlyBar = bar.AsReadOnly();
    }

    public IList<T> Bar
    {
        get { return readonlyBar; }
    }
}

OTHER TIPS

You can return an instance of ReadOnlyCollection from your method:

return new ReadOnlyCollection(items);

A property which encapsulates part of an object's mutable state may, if the type is a mutable class, represent any of these:

  1. A live mutable view of the property's state
  2. A mutable view of a detached copy of the property's state
  3. 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:

  1. A guaranteed-"live" read-only view of the property's state
  2. An immutable copy of the state as of the time it was called
  3. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top