向集合中添加元素的方法

3

我只是好奇,发现在C#中创建集合的方式有两种。对我来说,这只是一种风格,但也许有其他解释。性能?这是否对应一种模式?在示例2中唯一能看到的是防止集合被覆盖的一种方式。

示例1:

public class Employee
{
   ...
   public List<Phone> Phones
   {
      get; set;
   }
   ...
}

所以,来自另一个类
Employee employee = new Employee();
employee.Phones = this.GetPhones();

示例 2:

public class Employee
{
   ...
   private List<Phone> colPhones;
   public List<Phone> Phones
   {
      get
      {
         if(this.Phones == null)
         {
             this.Phones = new List<Phone>();
         }
         return this.Phones;
      }
   }
   ...
   public void AddPhone(Phone phone)
   {
       this.Phones.Add(phone);
   }
}

所以。
Employee employee = new Employee();
List<Phone> phones = this.GetPhones();
//--> Here, I know I can use for(int i....) instead of foreach. This is just for the example.
foreach(Phone phone in phones) 
{
   employee.Phones.Add(phone);
}

更新:

当我阅读马丁·福勒(Martin Fowler)的书《重构》时,发现了这个链接“封装集合”,这与已接受的答案是相同的概念。


1
在示例2中,“private List<Phone> colPhones;”看起来没有被使用 - 这是程序先前重写的产物吗? - RenniePet
1
应该使用this.colPholes而不是this.Phones来引用Phones getter内部的属性。否则,每当访问该属性时,都会出现循环引用,导致不断抛出StackOverflowExceptions异常。 - krillgar
2个回答

1

当执行以下代码时,私有成员变量会在代码的IL级别下创建。

public List<Phone> Phones { get; set; }

第二种方法是实现延迟加载的一种方式。通常情况下,不会执行 this.Phones = new List<Phone>();,而是提供一个方法从数据库中生成集合。使用第二种方案的另一个原因是,避免覆盖任何现有的集合,但在引用属性时避免出现 NullReferenceException
对于您95%的情况,第一种方案就足够了。
在这两个示例中,没有阻止 Employee 类的使用者执行以下操作:employee.Phones.Add(new Phone())。除非将属性设置为 readonly,否则无法防止修改集合,但这样做会导致只能在 Employee 类的构造函数中设置它,然后您的 AddPhone() 方法将变得无法使用。

1

我认为你的第一个例子相当危险。你自己说它容易被“覆盖”,但如果你不非常小心,它更容易受到集合中微妙修改的攻击。

Employee employee = new Employee();
List<Phone> obscureTemporaryVariable = this.GetPhones();
employee.Phones = obscureTemporaryVariable;
...
// much later, after having forgotten all about the above bit of code
obscureTemporaryVariable.Clear();
obscureTemporaryVariable.Add(new Phone(42));

现在你已经(可能是无意中)修改了“员工”电话号码。


1
第二个例子也更符合“不要和陌生人说话”的原则。 - Dzyann
除此之外,这两个示例都允许修改任何成员。如果您想确保集合中的任何内容都不会被修改,那么您需要将属性设置为“只读”,并仅通过构造函数进行设置。 - krillgar
我接受了你的答案,因为我正在阅读Martin Fowler的《重构》一书。在这本书中,有一张图片很好地概括了它。http://refactoring.com/catalog/encapsulateCollection.html 我读了这种策略的动机,它与你所说的非常相似。感谢你的回答。 - Maximus Decimus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接