Prashant Cholachagudda
Prashant Cholachagudda

Reputation: 13092

How to restrict to add an item to List<T>?

I have Class called Person containing to properties, Father and List of Children.

I want every one to use only AddChild Method to add children, not the List.Add method , so how do I restrict use of it?

public class Person
{
  private List<Person> _children = new List<Person>();
  public string Name { get; set; }
  public Person Father { get; set; }
  public List<Person> Children 
  { 
    get
    {
       return _children;
    } 
  }
  public void AddChild(string name)
  {
      _children.Add( new Person { Name = name, Father = this });
  }
}

Upvotes: 5

Views: 4377

Answers (7)

chwarr
chwarr

Reputation: 7202

If you are using .NET 4.5 or greater, you can return _children as IReadOnlyList<T>:

public IReadOnlyList<Person> Children
{
    get
    {
        return _children;
    }
}

How is this different from returning an IList<Person> via _children.AsReadOnly()? IReadOnlyList<Person> doesn't even have the mutation methods. Consider the following code:

somePerson.Children[0] = null;

When using IReadOnlyList<Person> this code will fail to compile. When using .AsReadOnly() this code will result in a runtime exception.

How is this different from returning an ReadOnlyCollection<Person> via _children.AsReadOnly()? There's no ReadOnlyCollection<Person> wrapper object created. Aside from that, I'm not seeing a huge difference.

Upvotes: 3

Wedge
Wedge

Reputation: 19805

An IEnumerable works just fine:

public IEnumerable<Person> Children
{
    get
    {
        return _children.AsReadOnly();
    }
}

or the more long winded:

public IEnumerable<Person> Children
{
    get
    {
        foreach (Person child in _children)
        {
            yield return child;
        }
    }
}

Upvotes: 2

devnull
devnull

Reputation: 2860

Expose the Children property as ReadOnlyCollection<Person>

public ReadOnlyCollection<Person> Children
{
     get {return _children.AsReadOnly();}
}

Upvotes: 3

Alex Reitbort
Alex Reitbort

Reputation: 13696

Expose Children as IEnumerable<T>

Upvotes: 8

Thomas Weller
Thomas Weller

Reputation: 11717

Change your Children property to this:

public IList<Person> Children 
{ 
  get
  {
     return _children.AsReadOnly();
  } 
}

Upvotes: 8

Marc Gravell
Marc Gravell

Reputation: 1062745

If you are exposing the underlying List<T>, then in short: you can't.

You could write your own collection-wrapper class, or perhaps inherit from Collection<T> (which still exposes Add, but you can override a few things to sense-check data before it is added).

Upvotes: 7

Pawel Lesnikowski
Pawel Lesnikowski

Reputation: 6381

Expose Children as ReadOnlyCollection:

public IList<Person> Children  
{  
    get 
    { 
       return new ReadOnlyCollection<Person>(_children);
    }  
} 

Upvotes: 12

Related Questions