Question

How do you manage this simple scenario when you have an object with a list of items. EG:

public class ContainerObject
{
    IList<ChildObject> Children { get; }

    public void AddCustom(ChildObject toAdd)
    {
        // Some validation ...
        Children.Add(toAdd);
    }
}

Assuming the collection is initialised to an implementation of IList, is there any way in which to control the way in which items are added to the list?

For example, I have another method on the ContainerObject class that takes a ChildObject and adds it to the list. This method is required to perform some basic validation on the ChildObject before adding it.

I am being lazy in that I don't want to mess around and write a custom list interface (without an add method) that consuming developers need to implement. I am also using the ToList() method on the IQueryable interface so this is another reason for sticking with IList - it just works.

So, is there an approach in which you can police how items are added to the IList instance i.e. prevent use of the Add method and only allow adding to the collection via my custom method, or am I just asking for the impossible? ... and being lazy :(

I can think of a few hacky ways in which to check when items are added via my custom method or directly on the list but these seem hacky!

Anyone experience anything similar to this? If so, what did you do?

Was it helpful?

Solution

Return a ReadOnlyCollection to the world wrapping your list which you manage the Adds to.

OTHER TIPS

You can make your property return a wrapper around the original list using ReadOnlyCollection<T>. This will ensure that callers don't add any items themselves. You can keep a reference to the original mutable list. Note that because the read-only collection is only a wrapper, callers which cache the read-only collection will still see additions that you make to the original list. That may or may not be a good thing depending on your expected use.

EDIT: To explain my caching comment...

Suppose a client did:

IList<ChildObject> originalChildren = container.Children;    
container.AddChild(new ChildObject());
IList<ChildObject> updatedChildren = container.Children;    

with the Children property implemented like this:

private IList<ChildObject> children = new List<ChildObject>();
public IList<ChildObject> Children
{
    get { return new ReadOnlyCollection<ChildObject>(children); }
}

Then originalChildren and updateChildren would both have the same contents - the returned ReadOnlyCollection wouldn't be a snapshot of the collection of children at the first line. It would just be a wrapper around the collection. Clients wouldn't be able to rely on it not changing - they just wouldn't be able to change it themselves.

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