Do | Ensure that each type is a well-defined set of related members, not just a random collection of unrelated functionality. |
Do | Use namespaces to organize types into a hierarchy of related feature areas. |
Avoid | Very deep namespace hierarchies. |
Avoid | Having too many namespaces. |
Avoid | Having types designed for advanced scenarios in the same namespace as types intended for common programming tasks. |
Do Not | Define types without specifying their namespaces. |
Do | Use a namespace with the “.Design” suffix to contain types that provide design-time functionality for a base namespace. |
Do | Use a namespace with the “.Permissions” suffix to contain types that provide custom permissions for a base namespace. |
Do | Use a namespace with the “.Interop” suffix to contain types that provide interop functionality for a base namespace. |
Do | Use a namespace with the “.Interop” suffix for all code in a Primary Interop Assembly (PIA). |
Consider | Defining 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 Not | Define 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. |
Do | Favor defining classes over interfaces. |
Do | Use abstract classes instead of interfaces to decouple the contract from implementations. |
Do | Define an interface if you need to provide a polymorphic hierarchy of value types. |
Consider | Defining interfaces to achieve a similar effect to that of multiple inheritance. |
Do Not | Define public or protected-internal constructors in abstract types. |
Do | Define a protected or an internal constructor on abstract classes. |
Do | Provide at least one concrete type that inherits from each abstract class that you ship. |
Do | Use static classes sparingly. |
Do Not | Treat static classes as a miscellaneous bucket. |
Do Not | Declare or override instance members in static classes. |
Do | Declare static classes as sealed, abstract, and add a private instance constructor, if your programming language does not have built in support for static classes. |
Do | Define an interface if you need some common API to be supported by a set of types that includes value types. |
Consider | Defining an interface if you need to support its functionality on types that already inherit from some other type. |
Avoid | Using marker interfaces (interfaces with no members). |
Do | Provide at least one type that is an implementation of an interface. |
Do | Provide 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 Not | Add members to an interface that has previously shipped. |
Do Not | Provide a default constructor for a struct. |
Do | Ensure that a state where all instance data is set to zero, false, or null (as appropriate) is valid. |
Do | Implement IEquatable<T> on value types. |
Do Not | Explicitly extend System.ValueType. |
Do | Use an enum to strongly type parameters, properties, and return values that represent sets of values. |
Do | Favor using an enum over static constants. |
Do Not | Use an enum for open sets (such as the operating system version, names of your friends, etc.). |
Do Not | Provide reserved enum values that are intended for future use. |
Avoid | Publicly exposing enums with only one value. |
Do Not | Include sentinel values in enums. |
Do | Provide a value of zero on simple enums. |
Consider | Using 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. |
Do | Name flag enums with plural nouns or noun phrases and simple enums with singular nouns or noun phrases. |
Do Not | Extend System.Enum directly. |
Do | Apply the System.FlagAttribute to flag enums. |
Do | Use powers of two for the flags enum values so they can be freely combined using the bitwise OR operation. |
Consider | Providing special enum values for commonly used combinations of flags. |
Avoid | Creating flag enums where certain combinations of values are invalid. |
Avoid | Using flag enum values of zero, unless the value represents “all flags are cleared” and is named appropriately as prescribed on page 99. |
Do | Name the zero-value of flag enums None. |
Consider | Adding values to enums, despite a small compatibility risk. |
Do | Use nested types when the relationship between the nested type and its outer type is such that member-accessibility semantics are desirable. |
Do Not | Use public nested types as a logical grouping construct; use namespaces for this. |
Avoid | Publicly exposed nested types. |
Do Not | Use nested types if the type is likely to be referenced outside of the containing type. |
Do Not | Use nested types if they need to be instantiated by client code. |
Do Not | Define a nested type as a member of an interface. |