Как ограничить добавление элемента в список <T>? - PullRequest
4 голосов
/ 07 октября 2009

У меня есть класс с именем Person, содержащий свойства, Отец и Список детей.

Я хочу, чтобы каждый использовал только метод AddChild для добавления детей, а не метод List.Add, так как я могу ограничить его использование?

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 });
  }
}

Ответы [ 7 ]

12 голосов
/ 07 октября 2009

Выставить детей как ReadOnlyCollection:

public IList<Person> Children  
{  
    get 
    { 
       return new ReadOnlyCollection<Person>(_children);
    }  
} 
8 голосов
/ 07 октября 2009

Измените свойство "Дети" на:

public IList<Person> Children 
{ 
  get
  {
     return _children.AsReadOnly();
  } 
}
8 голосов
/ 07 октября 2009

Expose Children as IEnumerable<T>

7 голосов
/ 07 октября 2009

Если вы выставляете базовый List<T>, то вкратце: вы не можете.

Вы можете написать свой собственный класс-упаковщик или, возможно, унаследовать от Collection<T> (который по-прежнему предоставляет Add, но вы можете override несколько вещей для проверки данных перед их добавлением).

3 голосов
/ 27 ноября 2013

Если вы используете .NET 4.5 или выше, вы можете вернуть _children как IReadOnlyList<T>:

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

Чем это отличается от возврата IList<Person> через _children.AsReadOnly()? IReadOnlyList<Person> даже не имеет методов мутации. Рассмотрим следующий код:

somePerson.Children[0] = null;

При использовании IReadOnlyList<Person> этот код не будет скомпилирован. При использовании .AsReadOnly() этот код приведет к исключению времени выполнения.

Чем это отличается от возврата ReadOnlyCollection<Person> через _children.AsReadOnly()? Там нет ReadOnlyCollection<Person> созданного объекта-оболочки. Кроме того, я не вижу большой разницы.

3 голосов
/ 07 октября 2009

Экспонировать собственность детей как ReadOnlyCollection<Person>

public ReadOnlyCollection<Person> Children
{
     get {return _children.AsReadOnly();}
}
2 голосов
/ 07 октября 2009

IEnumerable отлично работает:

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

или более длинные:

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