Ordering and Grouping Type Members

Question
You want to know how to best organize type members.

Answer
Group members of the same kind: for example, fields, methods, properties, and so on. Use a #region directive to make collapsing them easier.

Example
Feel free to adopt the following order when defining type members.

1. Event and delegate definitions
2. Private and public fields, except those backed by properties
3. Constructors, including static constructors
4. Instance public properties (and the private fields they back)
5. Instance public methods
6. Static public methods and properties
7. Methods in interfaces
8. Private helper methods

Member Names and Case Sensitivity

Question
Is it okay to give type members names that differ only in their casing?

Answer
You never want to define public members using names that differ only in their casing. You should also avoid giving private members names that differ only in their casing.

Comments
Why? It’s harder to read code when names differ only in their case.

Examples

class User
{
    // Not good. Two properties that only differ in case.
    public string UserName { get; set; }
    public string userName { get; set; }
}

class Card
{
    // Also not good. Two methods that only differ in case.
    public int Count()
    {
        ...
    }

    public int count()
    {
        ...
    }
}

Dependency on External Variables

Problem
You want to know how to best handle dependencies on external variables.

Answer
In general, the code inside a type should not reference any external variables. Apply this rule to global variables in a class or static fields or properties exposed by another type. Assign any value that a type needs to the type’s properties or pass them as arguments to its constructors or methods.

Comments
Why should you follow this rule? You should follow this rule because self-containment is the key to code reuse. If a type doesn’t depend on other types, then you can reuse the component in a different project with few or no side effects. By following this rule, it’s not possible to assign an invalid value to an external variable. Thus, the code in a type can’t break by accident or on purpose. Sometimes, you may want to relax this rule. This may be the case when you have complex object hierarchies. For example, you may have a class that contains all config settings for an assembly. In this scenario, the types may read values from static fields in the configuration class. If you can’t relax the rule, implement external values as properties instead of fields. This way, you can validate them and ensure they are never invalid. When a few (2-3) types depend on one another, mitigate this rule by storing them all in the same source file.

The Complexity of Types

Question
What should you do when you have a type that exposes many methods and/or properties?

Answer
Consider splitting the type into one main class and one or more dependent classes.

Comments
Why should you split a type with many properties or methods with similar names? Because the code in smaller types can be reused more easily.

Example
Let’s say you have a Contact class with many similar properties such as HomeAddress, HomeCity, HomeZip, and HomeState. Such a type can be better modeled with two different types, Contact and Location, where Contact exposes one property of type Location. The benefit of having a distinct Location type becomes evident if you later decide to implement other similar properties, such as Work.

public class Contact
{
    public Location Home
    {
        ...
    }
}

Abbreviations and Acronyms in Identifiers

Problem
You want to know the rules for using abbreviations and acronyms in type and member names.

Solution
Follow these guidelines to determine how you should use abbreviations and acronyms:

1. Avoid abbreviations in type and member names.
2. Only use acronyms if they are well known by developers (e.g. UIThread).
3. Two-character acronyms should use an all-uppercase style.
4. Use PascalCase for acronyms with three or more characters.

Comments
These conventions come from Microsoft, but you may notice that some classes in the .NET Framework do not follow them. For example, ASCIIEncoding and CLSCompliant.