In addition to following the pattern outlined below, collections should follow these guidelines:
Do name List Collections with a suffix of “Collection”
OrdersCollection, ButtonsCollection
Do implement ICollection on all collection classes.
Do provide a default-indexed property (indexer) named Item that returns a single item in the list.
class OrderCollection : ICollection { public OrderItem this[int index] { get ; set; } }
Do use strongly typed collections
Do use plural names for properties that are collections
Do use multiple homogeneous collections rather than a single heterogeneous collection.
For instance:
class MyBedroom { BooksCollection Books { get ; } ToysCollection Toys { get ; } } class BooksCollection: ICollection { public default Book Item[String name] { get ; set ; } } class ToysCollection: ICollection { public Default Toy Item[String name] { get ; set ; } }
Rather than a single collection of both Toys and Books.
Do implement IList as a private interface.
Do use collections for subvalues of an object.
Do extend BaseList.
Do not use indexed methods (e.g. methods that take an index as a parameter) as a substitute for a true collection class. Our developers find them confusing.
Consider not creating collections with public constructors.
Collection instances are not created directly by the developer. The developer only gets the instance from the object that contains the collection. The idea is that for Components where you have properties of type "collection", that you would follow use a factory design pattern. General use collection (which pretty much only exist in "System.Collections") would have public constructors, however "WinForms.ControlsCollection" that is used by Control.Controls, would not.
public class FooBarsCollection : ICollection { FooBarsCollection() { // non public constructor } }
Do include the owning class name in the name of the collection if it has an owning class.
If a Foo class has a collection of Bar subobjects named Bars, then the type returned from the property is named FooBars:
public class Foo { FooBars bars; public FooBars Bars { get { return bars; } } }
This convention allows collections containing the same type of object to expose different functionality, e.g. a read only collection, a read/write collection, etc.
Do use Indexed properties only on collections that have unambigious key types.
Support more than one lookup key on a collection using overloaded index properties. The type of lookup is unambiguous given the type of the key. For example:
public class FooBarsCollection : ICollection { public Bar this[int index] { get { } set { } } public Bar this[string index] { get { } set { } } }
Do follow the pattern that the Add method of a collection adds the value to the end of the collection if the collection is ordered linearly and allows additions.
Do use private interface implementation to enable strongly typed collections.