Правильное использование свойств при работе с коллекцией - PullRequest
3 голосов
/ 20 мая 2009

Мне интересно, как лучше всего использовать свойства при работе с коллекциями.

Например, у меня есть класс Foo, и я хочу сохранить список этого класса. Что из следующего следует использовать:

private List<Foo> myList;
private List<Foo> myOtherList = new List<Foo>();

сейчас для свойства:

public List<Foo> ListOfFoo
  {
     get 
     { 
        return myList; 
     }
     set 
     { 
        myList= new List<Foo>(value); 
     }
  }

Или набор должен быть равным значению?

public List<Foo> ListOfFoo
  {
     get 
     { 
        return myList; 
     }
     set 
     { 
        myList= value; 
     }
  }

Ответы [ 5 ]

2 голосов
/ 20 мая 2009

Как правило, вы не хотите использовать свойства расширенного типа, такие как List<T> (обычно можно использовать Collection<T>), и обычно свойства типа коллекции доступны только для чтения - сама коллекция может быть изменена с помощью методов. как Clear, Add и т. д., и этого обычно достаточно.

Например:

class Foo
{
    Collection<Bar> _bars = new Collection<Bar>();

    public Collection<Bar> Bars { get { return _bars; } }
}

Это также оставляет вас открытым для проверки изменений в коллекции путем реализации потомка Collection<T> и переопределения методов InsertItem, SetItem и т. Д.

2 голосов
/ 20 мая 2009

Выберите

private List<Foo> myOtherList = new List<Foo>();

, потому что другой просто объявляет ссылку (которая имеет значение null), в примере выше объявляется ссылка на список, создается список и назначается этот новый список для ссылки.

Выберите

public List<Foo> ListOfFoo
  {
     get { return myList; }
     set { myList= new List<Foo>(value); }
  }

Когда вы хотите, чтобы myList НЕ ссылался на какие-либо изменения, которые происходят со списком после его присвоения myList, например,

List<string> myFirstList = new List<string>();
myFirstList.Add("Hello");
myFirstList.Add("World");

List<string> mySecondList = new List<string>(myFirstList); 
// mySecondList now contains Hello & world

myFirstList.Add("Boyo");
// myFrist List now contains Hello, world & Boyo
// mySecondList still contains Hello & world

Выберите

public List<Foo> ListOfFoo
  {
     get { return myList; }
     set { myList= value; }
  }

Когда вы хотите, чтобы обе ссылки указывали на один и тот же объект, например

List<string> myFirstList = new List<string>();
myFirstList.Add("Hello");
myFirstList.Add("World");

List<string> mySecondList = myFirstList; 
// mySecondList now contains Hello & world

myFirstList.Add("Boyo");
// myFrist List now contains Hello, world & Boyo
// mySecondList "also" contains Hello, world & Boyo 

Выше "также" в кавычках, потому что на самом деле есть только один список, и моя первая и вторая точка указывают на один и тот же список.

0 голосов
/ 20 мая 2009

Почему бы не использовать IEnumerator-Interface в классе, а если вам нужно использовать установщик, используйте определенный метод.

Таким образом, вы также скрываете фактическую реализацию List.

class FooBar : IEnumerator
{
  private Collection<Foo> col;

  public IEnumarator GetEnumerator()
  {
    return col.GetEnumerator();
  }

  public void SetList(Collection col)
  {
    this.col= col; // you can also make this more general and convert the parameter so it fits your listimpl.
  }
}

class Clazz
{
  private void WhatEver(){
    FooBar foobar = new FooBar();
    ...
    foreach(Foo f in foobar)
    {...}
  }
}
0 голосов
/ 20 мая 2009

Как правило, предоставьте только интерфейс (ICollection, IList или аналогичный) и сделайте его доступным только для чтения:

private IList<Foo> m_list = new List<Foo>();
public IList<Foo> List {get { return m_list; } }

Преимущество: Вы можете изменить реализацию, например, перейти от списка к наблюдаемому списку. Возможно, вам придется сделать m_list элементом конкретного типа, а не интерфейсом, например использовать дополнительную функциональность.

С настраиваемым внешним списком вы столкнетесь с несколькими проблемами. Однако в некоторых случаях это необходимо:

  • данные могут создаваться извне, они могут быть большими и часто изменяться (например, десятки тысяч элементов)
  • внешний список должен быть общим для разных экземпляров
0 голосов
/ 20 мая 2009

Это зависит.

Когда используется первый стиль, вы создаете копию списка, которая обычно не нужна. Соглашение .Net предназначено для установщика, чтобы назначить ссылку на свойство. Вот почему я бы склонялся ко второму варианту.

Однако, если вы собираетесь выполнить операцию копирования, первым вариантом будет то, что вы ищете.

...