处理集合时正确使用属性

时间:2009-05-20 13:31:07

标签: c# collections properties

我想知道在处理集合时使用属性的最佳方法是什么。

例如,我有一个类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 个答案:

答案 0 :(得分:2)

通常,您不希望使用类似List<T>的富类型的属性(通常会使用Collection<T>),并且通常集合类型的属性是只读的 - 集合本身可以可以使用ClearAdd等方法进行修改,这通常就足够了。

例如:

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

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

这也让您可以通过实现Collection<T>的后代并覆盖InsertItemSetItem等方法来验证对集合的修改。

答案 1 :(得分:2)

选择

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 

上面的“也”是引号,因为实际上只有一个列表,我的第一个和第二个列表都指向同一个列表。

答案 2 :(得分:0)

为什么不在类上使用IEnumerator-Interface,如果必须使用setter,请使用某种方法。

这样你也隐藏了实际的List-Implementation。

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)
    {...}
  }
}

答案 3 :(得分:0)

取决于。

使用第一个样式时,您可以创建列表的副本,这通常是不必要的。 .Net约定用于setter分配对属性的引用。这就是我倾向于第二种选择的原因。

但是,如果您打算进行复制操作,则第一个选项就是您要查找的内容。

答案 4 :(得分:0)

通常,只公开一个接口(ICollection,IList或类似的接口),并使其只读:

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

优势:您可以修改实施,例如从列表切换到可观察列表。您可能需要创建具体类型的m_list成员而不是接口,例如使用额外的功能。

使用可设置的外部列表,您会遇到一些问题。但是,在某些情况下需要这样做:

  • 数据可以在外部创建,可能很大,而且经常更改(例如成千上万的项目)
  • 外部列表应在不同实例之间共享