【问题标题】:Ways of adding elements to collections向集合中添加元素的方法
【发布时间】:2015-03-26 16:59:20
【问题描述】:

只是好奇,我看到了在 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 的名为“重构”的书时发现了此链接 Encapsulate collection,这与公认答案的概念相同。

【问题讨论】:

  • 在示例 2“私人列表 colPhones;”中看起来它是未使用的 - 以前重写程序的工件?
  • 应该使用。 OP 应该引用 this.colPholes,而不是 Phones getter 中的 this.Phones。否则,他们将获得一个循环引用,每当访问该属性时,该引用将不断抛出 StackOverflowExceptions。

标签: c# list collections


【解决方案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));

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

【讨论】:

  • 另外,第二个例子更符合“不要和陌生人说话”的原则。
  • 除了两个示例都允许修改任何成员。如果您想确保集合中没有任何内容被修改,那么您将不得不创建属性readonly,并仅通过构造函数进行设置。
  • 我接受了您的回答,因为我正在阅读 Martin Fowler 的一本名为“重构”的书。在这里,有一张书中的图片,很好地总结了它。 refactoring.com/catalog/encapsulateCollection.html我读过这个策略的动机,和你说的很相似。谢谢你的回答。
【解决方案2】:

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

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

第二种方法是实现延迟加载的一种方式。通常,不会执行this.Phones = new List&lt;Phone&gt;();,而是提供一种从数据库生成集合的方法。使用第二种方案的另一个原因是不覆盖任何现有集合,但在引用属性时避免担心NullReferenceExceptions。

对于 95% 的情况,第一种情况会很好。

在这两个示例中,没有什么可以阻止 Employee 类的使用者执行以下操作:employee.Phones.Add(new Phone())。除非您将属性设置为readonly,否则无法阻止修改集合,但是您只能在Employee 类的构造函数中设置它,然后您的AddPhone() 方法将变得无法使用。

【讨论】:

    猜你喜欢
    • 2015-08-13
    • 2023-04-05
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多