Is there a .NET collection interface that prevents adding objects?

Viewed 6820

I have a class that maintains list of objects of another class. List of objects is a public property. I would like to prevent users from adding and removing objects directly to list like this:

      MyObject.MyListProperty.Add(object);

Instead I want them to use method that will internally do some processing and then add object to list.

I have some ideas:

  • create descendant of List<T> and override add and remove
  • return fresh copy of list through property getter (list is relatively short, not more than 30 objects)

Is there some collection interface that does not have Add and Remove?

Edit:
I'm going to go with ReadOnlyCollection<T>. Reason is that wrapped collection can be updated and changes will be immediately visible in read only object (see MSDN code examples for ReadOnlyCollection<T> and AsReadOnly()). This allows that read only list be created only once.

The problem with IEnumerable is that object can be casted back to original List<T> and then directly manipulated.

7 Answers

You can use ReadOnlyCollection - wrap your collection in this and return the ReadOnlyCollection to users of your class:

return new ReadOnlyCollection(innerCollection);

Or using the AsReadOnly method of the List<T> class:

return innerCollection.AsReadOnly();

The IEnumerable interface will do what you need, as it only has one member GetEnumerator(), that will only let you iterate over items.

Maybe AsReadOnly method will do the trick, to hand a read-only instance to public.

Otherwise, IEnumerable<T> has no Add nor Remove, so you can do something like:

private List<int> _myList;
public IEnumerable<int> MyList
{
   get
   {
      return this._myList.ToList();
   }
}

I would rather go for the IEnumerable<T> (+ copy) as for ReadOnlyCollection<T>, because: changes to your base list (which your read-only collection is created from) will immediately show up in your instance of the read-only collection. this may cause locking and straaange problems :)

Your easiest option would be to expose your list as one of the following IEnumerable, ICollection ReadOnlyCollection via a public property.

So you could create your own type of list which exposes your Items as one of the above but has an internal method for the adding e.g.

public class MyList<MyType>
{
    private List<MyType> items;

    public MyList()
    {
        items = new List<MyType>();
    }

    public IEnumerable Items { get { return items.AsEnumerable(); } }
    public Add(MyType item)
    {
        // do internal processing
        items.Add(item);
    }
}

Out of the box, only IEnumerable<T> will provide this without exposing any Add and Remove public methods that might trick the client into getting a runtime exception.

If you want your public API to explicitely state that the collection is read-only and you need an indexer, you will have to write your own wrapper around existing List<T> or T[].

You could just give them an object which always returns an enumerator that they can use to access the structure?

ICollection (the non-generic version) only got IEnumerable + Count

Related