.Net Framework Design Guidelines

Type Design Guidelines

DoEnsure that each type is a well-defined set of related members, not just a random collection of unrelated functionality.
DoUse namespaces to organize types into a hierarchy of related feature areas.
AvoidVery deep namespace hierarchies.
AvoidHaving too many namespaces.
AvoidHaving types designed for advanced scenarios in the same namespace as types intended for common programming tasks.
Do NotDefine types without specifying their namespaces.
DoUse a namespace with the “.Design” suffix to contain types that provide design-time functionality for a base namespace.
DoUse a namespace with the “.Permissions” suffix to contain types that provide custom permissions for a base namespace.
DoUse a namespace with the “.Interop” suffix to contain types that provide interop functionality for a base namespace.
DoUse a namespace with the “.Interop” suffix for all code in a Primary Interop Assembly (PIA).
ConsiderDefining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.
Do NotDefine a struct unless the type has all of the following characteristics: 1. Logically represents a single value. 2. Has an instance size under 16 bytes. 3. Is immutable. 4. Itwill not have to be boxed frequently.
DoFavor defining classes over interfaces.
DoUse abstract classes instead of interfaces to decouple the contract from implementations.
DoDefine an interface if you need to provide a polymorphic hierarchy of value types.
ConsiderDefining interfaces to achieve a similar effect to that of multiple inheritance.
Do NotDefine public or protected-internal constructors in abstract types.
DoDefine a protected or an internal constructor on abstract classes.
DoProvide at least one concrete type that inherits from each abstract class that you ship.
DoUse static classes sparingly.
Do NotTreat static classes as a miscellaneous bucket.
Do NotDeclare or override instance members in static classes.
DoDeclare static classes as sealed, abstract, and add a private instance constructor, if your programming language does not have built in support for static classes.
DoDefine an interface if you need some common API to be supported by a set of types that includes value types.
ConsiderDefining an interface if you need to support its functionality on types that already inherit from some other type.
AvoidUsing marker interfaces (interfaces with no members).
DoProvide at least one type that is an implementation of an interface.
DoProvide at least one API consuming each interface you define (a method taking the interface as a parameter or a property typed as the interface).
Do NotAdd members to an interface that has previously shipped.
Do NotProvide a default constructor for a struct.
DoEnsure that a state where all instance data is set to zero, false, or null (as appropriate) is valid.
DoImplement IEquatable<T> on value types.
Do NotExplicitly extend System.ValueType.
DoUse an enum to strongly type parameters, properties, and return values that represent sets of values.
DoFavor using an enum over static constants.
Do NotUse an enum for open sets (such as the operating system version, names of your friends, etc.).
Do NotProvide reserved enum values that are intended for future use.
AvoidPublicly exposing enums with only one value.
Do NotInclude sentinel values in enums.
DoProvide a value of zero on simple enums.
ConsiderUsing Int32 (the default in most programming languages) as the underlying type of an enum unless any of the following are true: 1. The enum is a flags enum, and you have more than 32 values. 2. The underlying type needs to be different than Int32 for easier interoperability with unmanaged code expecting different size enums. 3. A smaller underlying type would result in substantial savings in space.
DoName flag enums with plural nouns or noun phrases and simple enums with singular nouns or noun phrases.
Do NotExtend System.Enum directly.
DoApply the System.FlagAttribute to flag enums.
DoUse powers of two for the flags enum values so they can be freely combined using the bitwise OR operation.
ConsiderProviding special enum values for commonly used combinations of flags.
AvoidCreating flag enums where certain combinations of values are invalid.
AvoidUsing flag enum values of zero, unless the value represents “all flags are cleared” and is named appropriately as prescribed on page 99.
DoName the zero-value of flag enums None.
ConsiderAdding values to enums, despite a small compatibility risk.
DoUse nested types when the relationship between the nested type and its outer type is such that member-accessibility semantics are desirable.
Do NotUse public nested types as a logical grouping construct; use namespaces for this.
AvoidPublicly exposed nested types.
Do NotUse nested types if the type is likely to be referenced outside of the containing type.
Do NotUse nested types if they need to be instantiated by client code.
Do NotDefine a nested type as a member of an interface.