你在哪里放收藏班?

时间:2009-10-15 16:15:05

标签: c# collections nested-class

我不确定是否已经有了这个术语,但为了这个问题,我们定义两个术语: peer 实现或嵌套实现来说明如何您在包含许多父/子实体关系的数据模型中实现集合类。

我使用术语peer来描述你在模型层中实现集合类的场景,以及实体类本质上使它们成为API中的对等体,如下所示:

public class ParentEntity
{
  private ChildEntityCollection children;
}

public class ChildEntity
{
}

public class ChildEntityCollection : ICollection<ChildEntity>
{
}

这里的主要优点是你可以在碰巧存储相同类型子节点的其他实体类中重用集合类。

我使用术语嵌套来描述将它们实现为嵌套类的场景,如下所示:

public class ParentEntity
{
  private ChildEntityCollection children;

  public class ChildEntityCollection : ICollection<ChildEntity>
  {
  }
}

public class ChildEntity
{
}

这里的主要优点是每个父级都可以实现自己的集合类,以最适合该特定父级的方式存储其子级。例如,一个父实体可能会发现一个数组数据结构运行良好而另一个可能使用一个splay树(我知道这个模糊不清,但它很好地说明了我的观点)。

我注意到Microsoft在各种.NET相关框架中使用这两个习惯用法。 System.Windows.Forms命名空间似乎很大程度上依赖于嵌套实现。我倾向于发现自己也喜欢这种方法,即使它需要更多的工作。

建议,意见,其他想法?

7 个答案:

答案 0 :(得分:5)

无论Microsoft过去做过什么,当前的.NET API设计指南都不鼓励创建在父类之外可见的嵌套类。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms229027.aspx

答案 1 :(得分:2)

另一种选择是将集合类嵌套在子类中,并将其命名为Collection。这样,你总是得到Child.Collection作为名称。

public class Child
{
  public class Collection : ICollection<Child>
  {
  }
}

public class Parent
{
  private Child.Collection children;
}

答案 2 :(得分:1)

我个人更喜欢对等实现,它促进了代码的重用,我不认为嵌套实现会这样做。如果另一个类需要实现存储相同元素集合的不同方式,那么可以轻松地为该场景实现另一个类,而不会限制代码重用。

嵌套设置还可以使一些开发人员将他们的代码紧密地耦合到父类。

答案 3 :(得分:1)

我也更喜欢同行方法。除非你从不在其父类之外使用它,否则没有理由嵌套集合(在这种情况下,它应该是一个私有的嵌套类。)

答案 4 :(得分:1)

当域模型中只有一个实体可以逻辑地包含子实体时,我只会使用嵌套排列。

例如,如果您有PieceOfMail类和MailPieces集合类

  class PieceOfMail { } 
  class MailPieces: Collection<PieceOfMail> { }

然后ShipingCompany类,MailBox类,PostOffice类,MailRoute类和MailManBag类都可以具有类型为MailPieces的组成属性,因此我使用“对等”技术。 / p>

但是otoh,在同一个域中,如果你有一个代表PostageDiscount类型的类,以及一个表示要应用于货件的一组折扣的集合类,那么可能只有ShipmentTransaction类可以逻辑地包含这些折扣的集合,然后我使用嵌套技术...

答案 5 :(得分:1)

你真的需要ChildEntityCollection吗?为什么不使用提供的集合类型?

  //why bother?
//public class ChildEntityCollection : ICollection<ChildEntity>{}

public class ParentEntity
{
   //choose one
  private ChildEntity[] children;
  private List<ChildEntity> childrenInList;
  private HashSet<ChildEntity> childrenInHashSet;
  private Dictionary<int, ChildEntity> childrenInDictionary;
   // or if you want to make your own, make it generic
  private Balloon<ChildEntity> childrenInBalloon;
}
public class ChildEntity
{
}

答案 6 :(得分:1)

我通常会尽量避免生成特定的集合类。有时您可能需要一个特殊的类,但在许多情况下,您只需使用Collection<T>命名空间中的ReadOnlyCollection<T>System.Collection.ObjectModel等泛型类。这节省了很多打字。您的所有馆藏都来自IEnumerable<T>等,并且很容易与LINQ集成。根据您的要求,您还可以将集合公开为ICollection<T>或其他集合接口,然后让具有特定要求的类使用高度优化的通用集合。

public class ParentEntity {

  Collection<ChildEntity> children = new Collection<ChildEntity>();

  public Collection<ChildEntity> Children {
    get {
      return this.children;
    }
  }

}

您也可以像这样包装IList<T>

public class ParentEntity {

  // This collection can be modified inside the class.
  List<ChildEntity> children = new List<ChildEntity>();

  ReadOnlyCollection<ChildEntity> readonlyChildren;

  public ReadOnlyCollection<ChildEntity> Children {
    get {
      return this.readOnlyChildren
        ?? (this.readOnlyChildren =
              new ReadOnlyCollection<ChildEntity>(this.children));
    }
  }

}