开发者

Where do you put collection classes?

I am not sure if there is already a nomenclature for this, but for the sake of this question lets define two terms: peer implementation or nested implementation to illustrate how you implement collection classes in a data model that contains many parent/child entity relationships.

I use the term peer to describe the scenario where you implement the collection classes in your model layer along side with the entity classes essentially making them peers in your API like so:

public class ParentEntity
{
  private ChildEntityCollection children;
}

public class ChildEntity
{
}

public class ChildEntityCollection : ICollection<ChildEntity>
{
}

The main advantage here is that you can reuse the collection class in other entity classes that happen to store children of the same type.

I use the term nested to describe the scenario where you implement them as a nested class like so:

public class ParentEntity
{
  private ChildEntityCollection children;

  public class ChildEntityCollection : ICollection<ChildEntity>
  {
  }
}

pub开发者_如何学Clic class ChildEntity
{
}

The main advantage here is that each parent can implement their own collection class to store its children in manner that is most optimized for that specific parent. For example, one parent entity may find that an array data structure works well whereas another may use a splay tree (obscure I know, but it illustrates my point well).

I have noticed that Microsoft uses both idioms in the various .NET related frameworks. The System.Windows.Forms namespace seems to rely heavily on nested implementations. I tend to find myself prefering this method as well even though it requires more work.

Recommendations, comments, alternative ideas?


Regardless of what Microsoft might have done in the past, the current .NET API design guidelines discourage creation of nested classes that are visible outside their parent classes. See http://msdn.microsoft.com/en-us/library/ms229027.aspx for details.


Another option is to nest the collection class in the child class, and just name it Collection. That way, you always get Child.Collection as the name.

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

public class Parent
{
  private Child.Collection children;
}


Personally I prefer the peer implementation, it promotes reuse of code which I don't think the nested implementation does. If another class needs to implement a different way of storing a collection of the same elements then another class can easily be implemented for that scenario without limiting code reuse.

A nested setup can also lead some developers to tightly couple their code to the parent class.


I also prefer the peer approach. There's really no reason to nest the collection unless you will never use it outside of its parent class (in that case, it should be a private nested class.)


I would only use the nested arrangement when there is only one Entity in the Domain model that can logically contain the child Entities.

For example if you had a PieceOfMail class and a MailPieces collection class

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

then the ShipingCompany class, and the MailBox class, and the PostOffice Class, and the MailRoute class, and the MailManBag class, could ALL have a constituent property typed as MailPieces, so I'd use the "peer" technique.

But otoh, in the same Domain, if you had a class representing a type of PostageDiscount, and a collection class representing a set of discounts to be applied to a shipment, it might be the case that ONLY the ShipmentTransaction class could logically contain a collection of those discounts, then I'd use the nested technique...


Do you really need a ChildEntityCollection? Why not use a collection type that is provided?

  //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
{
}


I generally try to avoid generating specific collection classes. Sometimes you may need a special class, but in many cases you can simply use generic classes like Collection<T> and ReadOnlyCollection<T> from the System.Collection.ObjectModel namespace. This saves a lot of typing. All your collections derive from IEnumerable<T> etc. and are easily integrated with LINQ. Depending on your requirements you could also expose your collections as ICollection<T> or another collection interface and then let classes with specific requirements use highly optimized generic collections.

public class ParentEntity {

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

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

}

You can also wrap an IList<T> like this:

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));
    }
  }

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜