Section 1: .NET Common Types Overview & Tutorial

There are two important aspects with the Common Type System (CTS) in the .NET Framework:
• CTS features inheritance. Types can be derived from base types. The derived type inherits methods and properties of a base type. The base type can be derived from some other type, where the derived type inherits the members of both base types in its inheritance tree. All types are derived from a single C# Object base type.
• CTS defines types as either value types or reference types, including all types in the .NET Framework CTS class library and user-defined types (UDTs). Types defined as structs are value types, and all the CTS numeric types are value structs and are sealed classes. Types defined as classes are reference types.

CTS types are all derived from System.Object, and, therefore, they are all derived from this base reference type. System.Value and System.Enums types are derived from System.Object which become the Value Struct Types. The other System.Object derived classes like Custom Classes, System.Arrarys, interfaces, System.Strings, etc., are reference types.

Value types directly contain their values, and they are in stack memory so there is no need for garbage collection.Therefore, when a value-type instance is created, a singlular place in memory is utilized to store the value. Primitive types like ints, floats, bools, and chars are also value types.. When the CLR operates on a value type, the runtime deals directly with the variable data very efficiently.

When a CTS reference type object is created, a location in memory holds the reference much like a C++ pointer. The stack, on the other hand, is a simple, but efficient first-in last-out (FILO) memory structure. When a method executes, the CLR bookmarks the top of the stack, and it pushes data onto the stack as the method is executed. When the method finishes executing, the CLR just resets the stack pops all the method’s memory allocations back to the original state.

On the other hand, Heap is a random collection of objects. This it allows the CLR to allocate or deallocate memory randomly. Unlike the stack, the heap requires the overhead of a memory manager and garbage collector to keep up with everything.

Section 2: Interface Class Reference Types

Although most APIs are best modeled using classes and structs, there are cases in which interfaces are more appropriate or are the only option. The CLR does not support multiple inheritance (i.e., CLR classes cannot inherit from more than one base class), but it does allow types to implement one or more interfaces in addition to inheriting from a base class. Therefore, interfaces are often used to achieve the effect of multiple inheritance. For example, IDisposable is an interface that allows types to support disposability independent of any other inheritance hierarchy in which they want to participate.
The other situation in which defining an interface is appropriate is in creating a common interface that can be supported by several types, including some value types. Value types cannot inherit from types other than ValueType, but they can implement interfaces, so using an interface is the only option in order to provide a common base type.
√ 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.
X AVOID using marker interfaces (interfaces with no members).
If you need to mark a class as having a specific characteristic (marker), in general, use a custom attribute rather than an interface.
√ DO provide at least one type that is an implementation of an interface.
Doing this helps to validate the design of the interface. For example, List is an implementation of the IList interface.
√ DO provide at least one API that consumes each interface you define (a method taking the interface as a parameter or a property typed as the interface). Doing this helps to validate the interface design. For example, List.Sort consumes the System.Collections.Generic.IComparer interface.
X DO NOT add members to an interface that has previously shipped. Doing so would break implementations of the interface. You should create a new interface in order to avoid versioning problems. Except for the situations described in these guidelines, you should, in general, choose classes rather than interfaces in designing managed code reusable libraries.

Section 3: Struct Value Types

The general-purpose value type is most often referred to as a struct, its C# keyword. This section provides guidelines for general struct design.
X DO NOT provide a default constructor for a struct. Following this guideline allows arrays of structs to be created without having to run the constructor on each item of the array. Notice that C# does not allow structs to have default constructors. X DO NOT define mutable value types.
Mutable value types have several problems. For example, when a property getter returns a value type, the caller receives a copy. Because the copy is created implicitly, developers might not be aware that they are mutating the copy, and not the original value. Also, some languages (dynamic languages, in particular) have problems using mutable value types because even local variables, when dereferenced, cause a copy to be made.
√ DO ensure that a state where all instance data is set to zero, false, or null (as appropriate) is valid. This prevents accidental creation of invalid instances when an array of the structs is created.
√ DO implement IEquatable on value types. The Object.Equals method on value types causes boxing, and its default implementation is not very efficient, because it uses reflection. Equals can have much better performance and can be implemented so that it will not cause boxing.
X DO NOT explicitly extend ValueType. In fact, most languages prevent this. In general, structs can be very useful but should only be used for small, single, immutable values that will not be boxed frequently.

Section 4: Abstract Class Reference Types

DO NOT define public or protected internal constructors in abstract types. Constructors should be public only if users will need to create instances of the type. Because you cannot create instances of an abstract type, an abstract type with a public constructor is incorrectly designed and misleading to the users. DO define a protected or an internal constructor in abstract classes.
A protected constructor is more common and simply allows the base class to do its own initialization when subtypes are created.
An internal constructor can be used to limit concrete implementations of the abstract class to the assembly defining the class.
√ DO provide at least one concrete type that inherits from each abstract class that you ship.

View .NET Encrypting/Decrypting Code PDF

Section 5: Static Class Reference Types

A static class is defined as a class that contains only static members (of course besides the instance members inherited from System.Object and possibly a private constructor). Some languages provide built-in support for static classes. In C# 2.0 and later, when a class is declared to be static, it is sealed, abstract, and no instance members can be overridden or declared. Static classes are a compromise between pure object-oriented design and simplicity. They are commonly used to provide shortcuts to other operations (such as System.IO.File), holders of extension methods, or functionality for which a full object-oriented wrapper is unwarranted (such as System.Environment).
√ DO use static classes sparingly. Static classes should be used only as supporting classes for the object-oriented core of the framework.
X DO NOT treat static classes as a miscellaneous bucket.
X 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.

Section 6: Enum Value Types

Enums are a special kind of value type. There are two kinds of enums: simple enums and flag enums. Simple enums represent small closed sets of choices. A common example of the simple enum is a set of colors. Flag enums are designed to support bitwise operations on the enum values. A common example of the flags enum is a list of options.
√ DO use an enum to strongly type parameters, properties, and return values that represent sets of values.
√ DO favor using an enum instead of static constants.
X DO NOT use an enum for open sets (such as the operating system version, names of your friends, etc.).
X DO NOT provide reserved enum values that are intended for future use. You can always simply add values to the existing enum at a later stage. See Adding Values to Enums for more details on adding values to enums. Reserved values just pollute the set of real values and tend to lead to user errors.
X AVOID publicly exposing enums with only one value. A common practice for ensuring future extensibility of C APIs is to add reserved parameters to method signatures. Such reserved parameters can be expressed as enums with a single default value. This should not be done in managed APIs. Method overloading allows adding parameters in future releases.
X DO NOT include sentinel values in enums. Although they are sometimes helpful to framework developers, sentinel values are confusing to users of the framework. They are used to track the state of the enum rather than being one of the values from the set represented by the enum.
√ DO provide a value of zero on simple enums. Consider calling the value something like "None." If such a value is not appropriate for this particular enum, the most common default value for the enum should be assigned the underlying value of zero.
√ CONSIDER using Int32 (the default in most programming languages) as the underlying type of an enum unless any of the following is true:
• The enum is a flags enum and you have more than 32 flags, or expect to have more in the future.
• The underlying type needs to be different than Int32 for easier interoperability with unmanaged code expecting different-size enums.
• A smaller underlying type would result in substantial savings in space. If you expect the enum to be used mainly as an argument for flow of control, the size makes little difference. The size savings might be significant if:
◦ You expect the enum to be used as a field in a very frequently instantiated structure or class.
◦ You expect users to create large arrays or collections of the enum instances.
◦ You expect a large number of instances of the enum to be serialized.
For in-memory usage, be aware that managed objects are always DWORD-aligned, so you effectively need multiple enums or other small structures in an instance to pack a smaller enum with in order to make a difference, because the total instance size is always going to be rounded up to a DWORD.
√ DO name flag enums with plural nouns or noun phrases and simple enums with singular nouns or noun phrases.
X DO NOT extend System.Enum directly. System.Enum is a special type used by the CLR to create user-defined enumerations. Most programming languages provide a programming element that gives you access to this functionality. For example, in C# the enum keyword is used to define an enumeration.
Designing Flag Enums
--------------------------------------------------------------------------------
√ DO apply the System.FlagsAttribute to flag enums. Do not apply this attribute to simple enums.
√ DO use powers of two for the flag enum values so they can be freely combined using the bitwise OR operation.
√ CONSIDER providing special enum values for commonly used combinations of flags. Bitwise operations are an advanced concept and should not be required for simple tasks. ReadWrite is an example of such a special value.
X AVOID creating flag enums where certain combinations of values are invalid.
X AVOID using flag enum values of zero unless the value represents "all flags are cleared" and is named appropriately, as prescribed by the next guideline.
√ DO name the zero value of flag enums None. For a flag enum, the value must always mean "all flags are cleared."
Adding Value to Enums
--------------------------------------------------------------------------------
It is very common to discover that you need to add values to an enum after you have already shipped it. There is a potential application compatibility problem when the newly added value is returned from an existing API, because poorly written applications might not handle the new value correctly.
√ CONSIDER adding values to enums, despite a small compatibility risk.
If you have real data about application incompatibilities caused by additions to an enum, consider adding a new API that returns the new and old values, and deprecate the old API, which should continue returning just the old values. This will ensure that your existing applications remain compatible.

Section 7: Nested Types

A nested type is a type defined within the scope of another type, which is called the enclosing type. A nested type has access to all members of its enclosing type. For example, it has access to private fields defined in the enclosing type and to protected fields defined in all ascendants of the enclosing type. In general, nested types should be used sparingly. There are several reasons for this. Some developers are not fully familiar with the concept. These developers might, for example, have problems with the syntax of declaring variables of nested types. Nested types are also very tightly coupled with their enclosing types, and as such are not suited to be general-purpose types. Nested types are best suited for modeling implementation details of their enclosing types. The end user should rarely have to declare variables of a nested type and almost never should have to explicitly instantiate nested types. For example, the enumerator of a collection can be a nested type of that collection. Enumerators are usually instantiated by their enclosing type, and because many languages support the foreach statement, enumerator variables rarely have to be declared by the end user.
√ DO use nested types when the relationship between the nested type and its outer type is such that member-accessibility semantics are desirable.
X DO NOT use public nested types as a logical grouping construct; use namespaces for this.
X AVOID publicly exposed nested types. The only exception to this is if variables of the nested type need to be declared only in rare scenarios such as subclassing or other advanced customization scenarios.
X DO NOT use nested types if the type is likely to be referenced outside of the containing type. For example, an enum passed to a method defined on a class should not be defined as a nested type in the class.
X DO NOT use nested types if they need to be instantiated by client code. If a type has a public constructor, it should probably not be nested. If a type can be instantiated, that seems to indicate the type has a place in the framework on its own (you can create it, work with it, and destroy it without ever using the outer type), and thus should not be nested. Inner types should not be widely reused outside of the outer type without any relationship whatsoever to the outer type.
X DO NOT define a nested type as a member of an interface. Many languages do not support such a construct.