.Net Framework Design Guidelines

Usage Guidelines

DoPrefer using collections over arrays in public APIs.
Do NotUse read-only array fields.
ConsiderUsing jagged arrays instead of multidimensional arrays.
DoName custom attribute classes with the suffix “Attribute”.
DoApply the AttributeUsageAttribute to custom attributes.
DoProvide settable properties for optional arguments.
DoProvide get-only properties for required arguments.
DoProvide constructor parameters to initialize properties corresponding to required arguments.
AvoidProviding constructor parameters to initialize properties corresponding to the optional arguments.
AvoidOverloading custom attribute constructors.
DoSeal custom attribute classes, if possible.
Do NotUse weakly typed collections in public APIs.
Do NotUse ArrayList or List<T> in public APIs.
Do NotUse Hashtable or Dictionary<TKey, Tvalue> in public APIs.
Do NotUse IEnumerator<T>, IEnumerator, or any other type that implements either of these interfaces, except as the return type of the GetEnumerator method.
Do NotImplement both IEnumerator<T> and the IEnumerable<T> on the same type.
DoUse the least specialized type possible as a parameter type.
AvoidUsing ICollection<T> or ICollection as a parameter just to access the Count property.
Do NotProvide settable collection properties
DoUse Collection<T> or a subclass of Collection<T> for properties or return values representing read / write collections.
DoUse ReadOnlyCollection<T> or a subclass of ReadOnlyCollection<T> for properties or return values representing read-only collections.
ConsiderUsing subclasses of generic base collections instead of using the collections directly.
DoReturn a subclass of Collection<T> or ReadOnlyCollection<T> from very commonly used methods and properties.
ConsiderUsing a keyed collection if the items stored in the collection have unique keys (names, Ids, etc.).
Do NotReturn null values from collection properties or from methods returning collections.
Do NotReturn snapshot collections from properties.
DoUse either a snapshot collection or a live Ienumerable<T> to represent collections that are volatile (i.e., can change without explicitly modifying the collection).
DoPrefer collections over arrays.
ConsiderUsing arrays in low-level APIs to minimize memory consumption and maximize performance.
DoUse byte arrays instead of collections of bytes.
Do NotUse arrays for properties if the property would have to return a new array (e.g., a copy of an internal array) every time the property getter is called.
Do NotInherit from non generic base collections such as CollectionBase.
DoImplement IEnumerable<T> on strongly typed non generic collections (collections created before Generics were available).
AvoidImplementing collection interfaces on types with complex APIs unrelated to the concept of a collection.
DoUse the “Collection” suffix in names of abstractions implementing IEnumerable (or any of its descendants), unless the type also implements IDictionary or IDictionary<TKey, TValue>.
DoUse the “Dictionary” suffix in names of abstractions implementing IDictionary or IDictionary<TKey, TValue>.
AvoidUsing any suffixes implying particular implementation, such as “LinkedList” or “Hashtable,” in names of collection abstractions.
ConsiderPrefixing collection names with the name of the item type.
ConsiderUsing the “ReadOnly” prefix in names of read-only collections, if a corresponding writable collection might be added or already exists in the framework.
Do NotImplement ICloneable.
Do NotUse ICloneable in public APIs.
ConsiderDefining the Clone method on types that need a cloning mechanism.
DoImplement IEquatable<T> on value types.
DoFollow the same guidelines as for overriding Object.Equals when implementing IEquatable<T>.Equals
DoOverride Object.Equals whenever implementing IEquatable<T>.
ConsiderOverloading operator== and operator!= whenever implementing IEquatable<T>.
DoImplement IEquatable<T> anytime you implement IComparable<T>.
ConsiderOverloading comparison operators (<, >, <=, >=) whenever you implement IComparable<T>.
DoComply with the contract defined for Object.Equals when overriding the method.
DoOverride GetHashCode whenever you override Equals.
ConsiderImplementing IEquatable<T> whenever overriding Object.Equals.
Do NotThrow exceptions from Equals.
DoOverride Equals on value types.
DoProvide an overload of Equals taking the value type parameter by implementing IEquatable<T>.
ConsiderOverriding Equals to provide value equality if a reference type represents a value.
DoOverride GetHashCode if you override Object.Equals.
DoEnsure that if the Object.Equals method returns true for any tow objects, GetHashCode returns the same value for these objects.
DoMake every effort to ensure that GetHashCode generates a random distribution of numbers for all objects of a type.
DoEnsure that GetHashCode returns exactly the same value regardless of any changes that are made to the object.
AvoidThrowing exceptions from GetHashCode.
DoOverride ToString whenever an interesting human-readable string can be returned.
DoTry to keep the string returned from ToString short.
ConsiderReturning a unique string associated with the instance.
DoPrefer a friendly name over a unique but not readable ID.
DoString formatting based on the current thread culture when returning culture-dependent information.
DoProvide overload ToString(string format), or implement IFormattable, if the string returned from ToString() is culture sensitive or there are various ways to format the string.
Do NotReturn an empty string or null from ToString.
AvoidThrowing exceptions from ToString.
DoEnsure that ToString has no observable side effects.
DoReport security-sensitive information through an override of ToString only after demanding an appropriate permission.
ConsiderHaving the output of ToString be a valid input for any parsing methods on this type.
DoUse System.Uri to represent URI and URL data.
ConsiderProviding string-based overloads for most commonly used members with System.Uri parameters.
Do NotAutomatically overload all Uri-based members with a version that accepts a string.
DoCall the Uri-based overloads if available.
Do NotStore URI/URL data in a string.
Do NotUse XmlNode or XmlDocument to represent XML data. Favor using instances of IXPathNavigable instead.
DoUse XmlReader or IXPathNavigable as input or output for methods that accept or return XML.
DoImplement IXPathNavigable on types representing an XML view of an underlying object model or data source.
Do NotSubclass XmlDocument if you want to create a type representing an XML view of an underlying object model or data source.
Do NotOverload one of the equality operators but not the other.
DoEnsure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics.
AvoidThrowing exceptions from equality operators.
DoOverload the equality operators on value types, if equality is meaningful.
AvoidOverloading equality operators on mutable reference types.
ConsiderNot overloading equality operators on reference types, even if you override Equals or implement IEquatable<T>.
AvoidOverloading equality operators on reference types if the implementation would be significantly slower than that of reference equality.