March 21, 2019
Hot Topics:

Type Design Guidelines for Reusable .NET Libraries

  • December 23, 2005
  • By Krzysztof Cwalina and Brad Abrams
  • Send Email »
  • More Articles »

Adding Values 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. Documentation, samples, and FxCop rules encourage application developers to write robust code that can help applications deal with unexpected values. Therefore, it is generally acceptable to add values to enums, but as with most guidelines there might be exceptions to the rule based on the specifics of the framework.

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.

CLEMENS SZYPERSKI Adding a value to an enum presents a very real possibility of breaking a client. Before the addition of the new enum value, a client who was throwing unconditionally in the default case presumably never actually threw the exception, and the corresponding catch path is likely untested. Now that the new enum value can pop up, the client will throw and likely fold.

The biggest concern with adding values to enums is that you don't know whether clients perform an exhaustive switch over an enum or a progressive case analysis across wider-spread code. Even with the FxCop rules above in place and even when it is assumed that client apps pass FxCop without warnings, we still would not know about code that performs things like if (myEnum == someValue) ... in various places.

Clients might instead perform point-wise case analyses across their code, resulting in fragility under enum versioning. It is important to provide specific guidelines to developers of enum client code detailing what they need to do to survive the addition of new elements to enums they use. Developing with the suspected future versioning of an enum in mind is the required attitude.

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.

// enclosing type
public class OuterType {
private string name;
// nested type
public class InnerType {
public InnerType(OuterType outer){
// the name field is private, but it works just fine

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 generalpurpose 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 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.

For example, the nested type needs to have access to private members of the outer-type.

public OrderCollection : IEnumerable {
Order[] data = …;
public IEnumerator GetEnumerator(){
return new OrderEnumerator(this);
// This nested type will have access to the data array
// of its outer type.
class OrderEnumerator : IEnumerator {

DO NOT use public nested types as a logical grouping construct; use namespaces for this.

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.

KRZYSZTOF CWALINA The main motivation for this guideline is that many less skilled developers don't understand why some type names have dots in them and some don't. As long as they don't have to type in the type name, they don't care. But the moment you ask them to declare a variable of a nested type, they get lost. Therefore, we, in general, avoid nested types and use them only in places where developers almost never have to declare variables of that type (e.g., collection enumerators).

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.

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, it seems to indicate that 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.

DO NOT define a nested type as a member of an interface. Many languages do not support such a construct.

In general, nested types should be used sparingly, and exposure as public types should be avoided.


This article presented guidelines that describe when and how to design classes, structs, and interfaces.

About the Authors

Krzysztof Cwalina is a Program Manager on the Common Language Runtime team at Microsoft Corporation. He began his career at Microsoft designing APIs for the first release of the .NET Framework. He has been responsible for several namespaces in the Framework, including System.Collections, System.Diagnostics, System.Messaging, and others. He was also one of the original members of the FxCop team. Currently, he is leading a companywide effort to develop, promote, and apply the design guidelines to the .NET Framework and WinFX. Krzysztof graduated with a B.S. and an M.S. in computer science from the University of Iowa.

Brad Abrams is a Program Manager on the .NET Framework team at Microsoft, where he has been designing the Framework Class Libraries for the past five years. He is the primary author of the .NET Framework Design Guidelines, the Common Language Specification, and the class libraries for the ECMA CLI specification.

About the Book

Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
By Krzysztof Cwalina and Brad Adams

Published: September 19, 2005, Paperback: 384 pages
Published by Addison-Wesley
ISBN: 0321246756
Retail price: $39.99
This material is from Chapter 4 of the book.

Page 6 of 6

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date