3

Naming Guidelines

Following a consistent set of naming conventions in the development of a framework can be a major contribution to the framework’s usability. It allows the framework to be used by many developers on widely separated projects. Beyond consistency of form, names of framework elements must be easily understood and must convey the function of each element.

The goal of this chapter is to provide a consistent set of naming conventions that results in names that make immediate sense to developers. Most of these naming guidelines are simply conventions that have no technical rationale. However, following them will ensure that the names are understandable and consistent.

Although adopting these naming conventions as general code development guidelines would result in more consistent naming throughout your code, the guidance here only applies to APIs that are publicly exposed (public or protected types and members, and parameters to public or protected members).

This chapter describes general naming guidelines, including how to use capitalization, mechanics, and certain specific terms. It also provides specific guidelines for naming namespaces, types, members, parameters, assemblies, and resources.

3.1 Capitalization Conventions

Because the Common Language Runtime (CLR) supports many languages that might or might not be case sensitive, case alone should not be used to differentiate names. However, the importance of case in enhancing the readability of names cannot be overemphasized. The guidelines in this chapter lay out a simple method for using case that, when applied consistently, make identifiers for types, members, and parameters easy to read.

3.1.1 Capitalization Rules for Identifiers

To differentiate words in an identifier, capitalize the first letter of each word in the identifier. Do not use underscores to differentiate words, or for that matter, anywhere in identifiers. There are two appropriate ways to capitalize identifiers, depending on the use of the identifier:

  • PascalCasing

  • camelCasing

The PascalCasing convention, used for all identifiers except parameter names, capitalizes the first character of each word (including acronyms more than two letters in length), as shown in the following examples:

PropertyDescriptor
HtmlTag

A special case is made for two-letter acronyms in which both letters are capitalized, as shown in the following identifier:

IOStream

The camelCasing convention, used only for parameter names, capitalizes the first character of each word except the first word, as shown in the following examples. As the example also shows, two-letter acronyms that begin a camel-cased identifier are both lowercase.

propertyDescriptor
ioStream
htmlTag

The following are two basic capitalization guidelines for identifiers:

Images DO use PascalCasing for the names of namespaces, types, members, and generic type parameters.

For example, use TextColor rather than Textcolor or Text_color. Single words, such as Button, simply have initial capitals. Compound words that are always written as a single word, like endpoint, are treated as single words and have initial capitals only. More information on compound words is given in section 3.1.3.

Images DO use camelCasing for parameter names.

Table 3-1 describes the capitalization rules for different types of identifiers.

Table 3-1: Capitalization Rules for Different Types of Identifiers

Identifier

Casing

Example

Namespace

Pascal

namespace System.Security { ... }

Type

Pascal

public class StreamReader { ... }

Interface

Pascal

public interface IEnumerable { ... }

Method

Pascal

public class Object {
  public virtual string ToString();
}

Property

Pascal

public class String {
  public int Length { get; }
}

Event

Pascal

public class Process {
  public event EventHandler Exited;
}

Field

Pascal

public class MessageQueue {
  public static readonly TimeSpan
InfiniteTimeout;
}
public struct UInt32 {
  public const MinValue = ʘ;
}

Enum value

Pascal

public enum FileMode {
  Append,
  ...
}

Type parameter, generic method

Pascal

public partial class Enum {
  public static TEnum Parse<TEnum>(
   string value) { ... }
}

Type parameter, generic type

Pascal

public class Task<TResult> {
  ...
}

Tuple element

Pascal

public partial class Range {
  public
  (int Offset, int Length)
  GetOffsetAndLength(
    int length) { ... }
}

Parameter

Camel

public class Convert {
  public static int ToInt32(string value);
}

3.1.2 Capitalizing Acronyms

In general, it is important to avoid using acronyms in identifier names unless they are in common usage and are immediately understandable to anyone who might use the framework. For example, HTML, XML, and IO are all well understood, but less well-known acronyms should definitely be avoided.

By definition, an acronym must be at least two characters. Acronyms of three or more characters follow the guidelines of any other word. Only the first letter is capitalized, unless it is the first word in a camel-cased parameter name, which is all lowercase.

As mentioned in the preceding section, two-character acronyms (e.g., IO) are treated differently, primarily to avoid confusion. Both characters should be capitalized unless the two-character acronym is the first word in a camel-cased parameter name, in which case both characters are lowercase. The following examples illustrate all of these cases:

Click here to view code image

public void StartIO(Stream ioStream, bool closeIOStream);
public void ProcessHtmlTag(string htmlTag)

Images DO capitalize both characters of two-character acronyms, except the first word of a camel-cased identifier.

Click here to view code image

System.IO
System.Threading.IOCompletionCallback
public void StartIO(Stream ioStream)

Images DO capitalize only the first character of acronyms with three or more characters, except the first word of a camel-cased identifier.

Click here to view code image

System.Xml
System.Xml.XmlNode
public void ProcessHtmlTag(string htmlTag)

Images DO NOT capitalize any of the characters of any acronyms, whatever their length, at the beginning of a camel-cased identifier.

3.1.3 Capitalizing Compound Words and Common Terms

Most compound terms are treated as single words for purposes of capitalization.

Images DO NOT capitalize each word in so-called closed-form compound words.

These are compound words written as a single word, such as endpoint. For the purpose of casing guidelines, treat a closed-form compound word as a single word. Use a current dictionary to determine if a compound word is written in closed form.

Table 3-2 shows capitalization for some of the most commonly used compound words and common terms.

Table 3-2: Capitalization and Spelling for Common Compound Words and Common Terms

Pascal

Camel

Not

BitFlag

bitFlag

Bitflag

Callback

callback

CallBack

Canceled

canceled

Cancelled

DoNot

doNot

Don't

Email

email

EMail

Endpoint

endpoint

EndPoint

Filename

filename

FileName

Gridline

gridline

GridLine

Hashtable

hashtable

HashTable

Id

id

ID

Indexes

indexes

Indices

Logoff1

logoff

LogOut

Logon1

logon

LogIn2

Metadata

metadata

MetaData, metaData

Multipanel

multipanel

MultiPanel

Multiview

multiview

MultiView

Namespace

namespace

NameSpace

Ok

ok

OK

Pi

pi

PI

Placeholder

placeholder

PlaceHolder

SignIn

signIn

SignOn

SignOut

signOut

SignOff

Timestamp

timestamp

TimeStamp

Username

username

UserName

WhiteSpace

whiteSpace

Whitespace

Writable

writable

Writeable

1. When used as a noun (properties, fields, parameters, types). As a verb (methods) it should be considered two words—for example, LogOff.

2. “Login” is now regarded as a closed-form noun, so a type with members named “Login” and “Password” would be OK, except in .NET we prefer “Logon” to “Login.” As a compound verb, “Log In” should be “Log On,” so “LogIn” is never used, and “LogOn” does not appear in this table.

Two other terms that are in common usage are in a category by themselves, because they are common slang abbreviations. The two words Ok and Id (cased as shown here) are exceptions to the guideline that no abbreviations should be used in names.

Table 3-2 and the rule about closed-form nouns are secondary to the general guideline of maintaining consistency. As of September 2019, “white space” is the dictionary entry, with some dictionaries having a note that computer science often uses it as a single word. If and when “whitespace” becomes an accepted closed-form noun, you should continue to use “WhiteSpace” in type hierarchies built with the older form of the word.

3.1.4 Case Sensitivity

Languages that can run on the CLR are not required to support case sensitivity, although some do. Even if your language supports it, other languages that might access your framework do not. Any APIs that are externally accessible, therefore, cannot rely on case alone to distinguish between two names in the same context.

There is really only one guideline for case sensitivity, albeit an important one.

Images DO NOT assume that all programming languages are case sensitive. They are not. Names cannot differ by case alone.

3.2 General Naming Conventions

This section describes general naming conventions that relate to word choice, guidelines on using abbreviations and acronyms, and recommendations on how to avoid using language-specific names.

3.2.1 Word Choice

It is important that names of framework identifiers make sense on first reading. Identifier names should clearly state what each member does and what each type and parameter represents. To this end, it is more important that the name be clear than that it be short. Names should correspond to scenarios, logical or physical parts of the system, and well-known concepts, rather than to technologies or architecture.

Images DO choose easily readable identifier names.

For example, a property named HorizontalAlignment is more English-readable than AlignmentHorizontal.

Images DO favor readability over brevity. The property name CanScrollHorizontally is better than ScrollableX (an obscure reference to the X-axis).

Images DO NOT use underscores, hyphens, or any other non-alphanumeric characters.

Images DO NOT use Hungarian notation.

Images AVOID using identifiers that conflict with keywords of widely used programming languages.

According to Rule 4 of the Common Language Specification (CLS), all compliant languages must provide a mechanism that allows access to named items that use a keyword of that language as an identifier. C#, for example, uses the @ sign as an escape mechanism in this case. However, it is still a good idea to avoid common keywords because it is much more difficult to use a method with the escape sequence than one without it.

Images DO use only ASCII characters in identifier names.

All of the identifiers in .NET use ASCII characters, so anyone working with .NET is capable of typing those characters and working with files or tools that understand those characters. But the developers who want to use your library may not have easy capability to type non-ASCII characters, or may use text editors (or other tools) that do not reliably preserve non-ASCII data.

When basing an identifier on a word that properly requires diacritical marks, either use (or invent) the diacritical-free approximation or choose a different identifier.

Table 3-3 describes some suggested replacement spellings to avoid diacritical marks. It is provided for clarity, but is neither authoritative nor exhaustive.

Table 3-3: Alternative Spellings to Avoid Diacritical Marks

Spelling with Diacritics

Spelling for an Identifier

Edelweiß

Edelweiss

Mêlée

Melee

Naïve

Naive

Résumé

Resume

Röntgen

Roentgen

3.2.2 Using Abbreviations and Acronyms

In general, do not use abbreviations or acronyms in identifiers. As stated earlier, it is more important for names to be readable than it is for them to be brief. It is equally important not to use abbreviations and acronyms that are not generally understood—that is, do not use anything that the large majority of people who are not experts in a given field would not know the meaning of immediately.

Images DO NOT use abbreviations or contractions as part of identifier names.

For example, use GetWindow rather than GetWin.

Images DO NOT use any acronyms that are not widely accepted, and even if they are, only when necessary.

For example, UI is used for User Interface and HTML is used for HyperText Markup Language. Although many framework designers feel that some recent acronym will soon be widely accepted, it is bad practice to use it in framework identifiers.

For acronym capitalization rules, see section 3.1.2.

3.2.3 Avoiding Language-Specific Names

Programming languages that target the CLR often have their own names (aliases) for the so-called primitive types. For example, int is a C# alias for System.Int32. To ensure that your framework can take full advantage of the cross-language interoperation that is one of the core features of the CLR, it is important to avoid the use of these language-specific type names in identifiers.

Images DO use semantically interesting names rather than language-specific keywords for type names.

For example, GetLength is a better name than GetInt.

Images DO use a generic CLR type name, rather than a language-specific name, in the rare cases when an identifier has no semantic meaning beyond its type.

For example, a method converting to System.Int64 should be named ToInt64, not ToLong (because System.Int64 is a CLR name for the C#-specific alias long). Table 3-4 presents several base data types using the CLR type names (as well as the corresponding type names for C#, Visual Basic, and C++).

Table 3-4: CLR Type Names for Language-Specific Type Names

C#

Visual Basic

C++

CLR

Sbyte

SByte

char

SByte

Byte

Byte

unsigned char

Byte

short

Short

short

Int16

ushort

UInt16

unsigned short

UInt16

int

Integer

int

Int32

uint

UInt32

unsigned int

UInt32

long

Long

__int64

Int64

ulong

UInt64

unsigned __int64

UInt64

float

Single

float

Single

double

Double

double

Double

bool

Boolean

bool

Boolean

char

Char

wchar_t

Char

string

String

String

String

object

Object

Object

Object

Images DO use a common name, such as value or item, rather than repeating the type name, in the rare cases when an identifier has no semantic meaning and the type of the parameter is not important.

The following is a good example of methods of a class that support writing a variety of data types into a stream:

void Write(double value);
void Write(float value);
void Write(short value);

3.2.4 Naming New Versions of Existing APIs

Sometimes a new feature cannot be added to an existing type, even though the type’s name implies that it is the best place for the new feature. In such a case, a new type needs to be added, which often leaves the framework designer with the difficult task of finding a good new name for the new type. Similarly, an existing member often cannot be extended or overloaded to provide additional functionality, so a member with a new name needs to be added. The guidelines that follow describe how to choose names for new types and members that supersede or replace existing types or members.

Images DO use a name similar to the old API when creating new versions of an existing API.

This helps to highlight the relationship between the APIs.

Click here to view code image

class AppDomain {
   [Obsolete("AppDomain.SetCachePath has been deprecated. Please use
AppDomainSetup.CachePath instead.")]
   public void SetCachePath(String path) { ... }
}

class AppDomainSetup {
   public string CachePath { get { ... }; set  { ... }; }
}

Images DO prefer adding a suffix rather than a prefix to indicate a new version of an existing API.

Images CONSIDER using a brand-new, but meaningful, identifier, instead of adding a suffix or a prefix.

Images DO use a numeric suffix to indicate a new version of an existing API, particularly if the existing name of the API is the only name that makes sense (e.g., if it is an industry standard) and if adding any meaningful suffix (or changing the name) is not an appropriate option.

Click here to view code image

// old API
[Obsolete("This type is obsolete. Please use the new version of the same
class, X509Certificate2.")]
public class X509Certificate { ... }
// new API
public class X509Certificate2 { ... }

Images DO NOT use the “Ex” (or a similar) suffix for an identifier to distinguish it from an earlier version of the same API.

Click here to view code image

[Obsolete("This type is obsolete. ...")]
public class Car  { ... }

// new API
public class CarEx      { ... } // the wrong way
public class CarNew     { ... } // the wrong way
public class Car2       { ... } // an acceptable way
public class Automobile { ... } // a better way

Images DO use the “64” suffix when introducing versions of APIs that operate on a 64-bit integer (a long integer) instead of a 32-bit integer. You only need to take this approach when the existing 32-bit API exists; don’t do it for brand-new APIs with only a 64-bit version.

For example, various APIs on System.Diagnostics.Process return Int32 values representing memory sizes, such as PagedMemorySize or PeakWorkingSet. To appropriately support these APIs on 64-bit systems, APIs have been added that have the same name but a “64” suffix.

Click here to view code image

public class Process {
   // old APIs
   public int PeakWorkingSet { get; }
   public int PagedMemorySize { get; }
   // ...
   // new APIs
   public long PeakWorkingSet64 { get; }
   public long PagedMemorySize64 { get; }
}

3.3 Names of Assemblies, DLLs, and Packages

An assembly is the unit of deployment and identity for managed code programs. Although assemblies can span one or more files, typically an assembly maps one-to-one with a dynamic-link library (DLL). Additionally, when a DLL is distributed via a package management system, the DLL and the package typically have the same name. Therefore, this section describes only DLL naming conventions, which then can be mapped to assembly naming conventions and package naming conventions.

Keep in mind that namespaces are distinct from DLL and assembly names. Namespaces represent logical groupings for developers, whereas DLLs and assemblies represent packaging and deployment boundaries. DLLs can contain multiple namespaces for product factoring and other reasons. Because namespace factoring is different than DLL factoring, you should design them independently. For example, if you decide to name your DLL MyCompany.MyTechnology, it does not mean that the DLL has to contain a namespace named MyCompany.MyTechnology, though it can.

Images DO choose names for your assembly DLLs that suggest large chunks of functionality, such as System.Data.

Assembly, DLL, and package names don’t have to correspond to namespace names, but it is reasonable to follow the namespace name when naming assemblies. A good rule of thumb is to name the DLL based on the common prefix of the namespaces contained in the assembly. For example, an assembly with two namespaces, MyCompany.MyTechnology.FirstFeature and MyCompany.MyTechnology.SecondFeature, could be called MyCompany.MyTechnology.dll.

Images CONSIDER naming DLLs according to the following pattern:

<Company>.<Component>.dll

<Component> can contain more than one dot-separated clauses. For example:

Click here to view code image

Microsoft.VisualBasic.dll
Microsoft.VisualBasic.Vsa.dll
Fabrikam.Security.dll
Litware.Controls.dll

3.4 Names of Namespaces

As with other naming guidelines, the goal when naming namespaces is to create sufficient clarity for the programmer using the framework to immediately know what the content of the namespace is likely to be. The following template specifies the general rule for naming namespaces:

Click here to view code image

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]

The following are examples:

Click here to view code image

Microsoft.VisualStudio
Microsoft.VisualStudio.Design
Fabrikam.Math
Litware.Security

Images DO prefix namespace names with a company name to prevent namespaces from different companies from having the same name.

For example, the Microsoft Office automation APIs provided by Microsoft should be in the namespace Microsoft.Office.

Images DO use a stable, version-independent product name at the second level of a namespace name.

Images DO NOT use organizational hierarchies as the basis for names in namespace hierarchies, because group names within corporations tend to be short-lived. Organize the hierarchy of namespaces around groups of related technologies.

Images DO use PascalCasing, and separate namespace components with periods (e.g., Microsoft.Office.PowerPoint). If your brand employs nontraditional casing, you should follow the casing defined by your brand, even if it deviates from normal namespace casing.

Images CONSIDER using plural namespace names where appropriate.

For example, use System.Collections instead of System.Collection. Brand names and acronyms are exceptions to this rule, however. For example, use System.IO instead of System.IOs.

Images DO NOT use the same name for a namespace and a type in that namespace.

For example, do not use Debug as a namespace name and then also provide a class named Debug in the same namespace. Several compilers require such types to be fully qualified.

These guidelines cover general namespace naming guidelines, but the next section provides specific guidelines for certain special subnamespaces.

3.4.1 Namespaces and Type Name Conf licts

Namespaces are used to organize types into a logical and easy-to-explore hierarchy. They are also indispensable in resolving type name ambiguities that might arise when importing multiple namespaces. However, that fact should not be used as an excuse to introduce known ambiguities between types in different namespaces that are commonly used together. Developers should not be required to qualify type names in common scenarios.

Images DO NOT introduce overly general type names such as Element, Node, Log, and Message.

There is a very high probability that doing so will lead to type name conflicts in common scenarios. You should qualify the general type names (e.g., FormElement, XmlNode, EventLog, SoapMessage).

There are specific guidelines for avoiding type name conflicts for different categories of namespaces. Namespaces can be divided into the following categories:

  • Application model namespaces

  • Infrastructure namespaces

  • Core namespaces

  • Technology namespace groups

3.4.1.1 Application Model Namespaces

Namespaces belonging to a single application model are very often used together, but they are almost never used with namespaces of other application models. For example, the System.Windows.Forms namespace is very rarely used together with the System.Web.UI namespace. The following are well-known application model namespace groups:

System.Windows*
System.Web.UI*

Images DO NOT give the same name to multiple types across namespaces within a single application model.

For example, do not add a type named Page to the System.Web.UI.Adapters namespace, because the System.Web.UI namespace already contains a type named Page.

3.4.1.2 Infrastructure Namespaces

This group contains namespaces that are rarely imported during development of common applications. For example, .Design namespaces are mainly used when developing programming tools. Avoiding conflicts with types in these namespaces is not critical.

System.Windows.Forms.Design
*.Design
*.Permissions
3.4.1.3 Core Namespaces

The core namespaces include all System namespaces, excluding namespaces of the application models and the Infrastructure namespaces. Core namespaces include, among others, System, System.IO, System.Xml, and System.Net.

Images DO NOT give types names that would conflict with any type in the core namespaces.

For example, never use Stream as a type name. It would conflict with System.IO.Stream, a very commonly used type.

By the same token, do not add a type named EventLog to the System.Diagnostics.Events namespace, because the System.Diagnostics namespace already contains a type named EventLog.

3.4.1.4 Technology Namespace Groups

This category includes all namespaces with the same first two namespace nodes (<Company>.<Technology>*), such as Microsoft.Build.Utilities and Microsoft.Build.Tasks. It is important that types belonging to a single technology do not conflict with each other.

Images DO NOT assign type names that would conflict with other types within a single technology.

Images DO NOT introduce type name conflicts between types in technology namespaces and an application model namespace (unless the technology is not expected to be used with the application model).

For example, you should not add a type named Binding to the Microsoft.VisualBasic namespace because the System.Windows.Forms namespace already contains that type name.

3.5 Names of Classes, Structs, and Interfaces

In general, class and struct names should be nouns or noun phrases, because they represent entities of the system. A good rule of thumb is that if you are not able to come up with a noun or a noun phrase name for a class or a struct, you probably should rethink the general design of the type. Interfaces representing roots of a hierarchy (e.g., IList<T>) should also use nouns or noun phrases. Interfaces representing capabilities should use adjectives and adjective phrases (e.g., IComparable<T>, IFormattable).

Another important consideration is that the most easily recognizable names should be used for the most commonly used types, even if the name fits some other less-used type better in the purely technical sense. For example, a type used in mainline scenarios to submit print jobs to print queues should be named Printer, rather than PrintQueue. Even though technically the type represents a print queue and not the physical device (printer), from the scenario point of view, Printer is the ideal name because most people are interested in submitting print jobs and not in other operations related to the physical printer device (e.g., configuring the printer). If you need to provide another type that corresponds, for example, to the physical printer to be used in configuration scenarios, the type could be called PrinterConfiguration or PrinterManager.

Similarly, names of the most commonly used types should reflect usage scenarios, not inheritance hierarchy. Most users use the leaves of an inheritance hierarchy almost exclusively; they are rarely concerned with the structure of the hierarchy. Yet API designers often see the inheritance hierarchy as the most important criterion for type name selection. For example, Stream, StreamReader, TextReader, StringReader, and FileStream all describe the place of each of the types in the inheritance hierarchy quite well, but they obscure the most important information for the majority of users: the type that they need to instantiate to read text from a file.

The naming guidelines that follow apply to general type naming.

Images DO name classes and structs with nouns or noun phrases, using PascalCasing.

This distinguishes type names from methods, which are named with verb phrases.

Images DO name interfaces with adjective phrases, or occasionally with nouns or noun phrases.

Nouns and noun phrases should be used rarely. They might indicate that the type should be an abstract class, rather than an interface. See section 4.3 for details about deciding how to choose between abstract classes and interfaces.

Images DO NOT give class names a prefix (e.g., “C”).

Images CONSIDER ending the name of derived classes with the name of the base class.

This is very readable and explains the relationship clearly. Two examples of this in code are ArgumentOutOfRangeException, which is a kind of Exception, and SerializableAttribute, which is a kind of Attribute. However, it is important to use reasonable judgment in applying this guideline; for example, the Button class is a kind of Control, although Control doesn’t appear in its name. The following are examples of correctly named classes:

Click here to view code image

public class FileStream : Stream {...}
public class Button : Control {...}

Images DO prefix interface names with the letter I, to indicate that the type is an interface.

For example, IComponent (descriptive noun), ICustomAttributeProvider (noun phrase), and IPersistable (adjective) are appropriate interface names. As with other type names, avoid abbreviations.

Images DO ensure that the names differ only by the “I” prefix on the interface name when you are defining a class–interface pair where the class is a standard implementation of the interface.

The following example illustrates this guideline for the interface IComponent and its standard implementation, the class Component:

Click here to view code image

public interface IComponent { ... }
public class Component : IComponent { ... }

3.5.1 Names of Generic Type Parameters

Generics were added to .NET Framework 2.0. This feature introduced a new kind of identifier called type parameter. The following guidelines describe naming conventions related to naming such type parameters:

Images DO name generic type parameters with descriptive names unless a single-letter name is completely self-explanatory and a descriptive name would not add value.

Click here to view code image

public interface ISessionChannel<TSession> { ... }
public delegate TOutput Converter<TInput,TOutput>(TInput from);
public struct Nullable<T> { ... }
public class List<T> { ... }

Images CONSIDER using T as the type parameter name for types with one single-letter type parameter.

Click here to view code image

public int IComparer<T> { ... }
public delegate bool Predicate<T>(T item);
public struct Nullable<T> where T:struct { ... }

Images DO prefix descriptive type parameter names with T.

Click here to view code image

public interface ISessionChannel<TSession> where TSession : ISession{
   TSession Session { get; }
}

Images CONSIDER indicating constraints placed on a type parameter in the name of the parameter.

For example, a parameter constrained to ISession might be called TSession.

3.5.2 Names of Common Types

If you are deriving from or implementing types contained in .NET, it is important to follow the guidelines in this section.

Images DO follow the guidelines described in Table 3-5 when naming types derived from or implementing certain .NET types.

Table 3-5: Name Rules for Types Derived from or Implementing Certain Core Types

Base Type

Derived/Implementing Type Guideline

System.Attribute

Images DO add the suffix “Attribute” to names of custom attribute classes.

System.Delegate

Images DO add the suffix “EventHandler” to names of delegates that are used in events.

Images DO add the suffix “Callback” to names of delegates other than those used as event handlers.

Images DO NOT add the suffix “Delegate” to a delegate.

System.EventArgs

Images DO add the suffix “EventArgs.”

System.Enum

Images DO NOT derive from this class; use the keyword supported by your language instead; for example, in C#, use the enum keyword.

Images DO NOT add the suffix “Enum” or “Flag.”

System.Exception

Images DO add the suffix “Exception.”

IDictionary IDictionary<TKey, TValue>

Images DO add the suffix “Dictionary.” Note that IDictionary is a specific type of collection, but this guideline takes precedence over the more general collections guideline that follows.

IEnumerable ICollection IList IEnumerable<T> ICollection<T> IList<T>

Images DO add the suffix “Collection,” except for reusable, specialized data types such as “Queue” and “HashSet.”

System.IO.Stream

Images DO add the suffix “Stream.”

These suffixing guidelines apply to the whole hierarchy of the specified base type. For example, it is not just types derived directly from System.Exception that need the suffixes, but also those derived from Exception subclasses.

These suffixes should be reserved for the named types. Types derived from or implementing other types should not use these suffixes. For example, the following represent incorrect naming:

Click here to view code image

public class ElementStream : Object { ... }
public class WindowsAttribute : Control { ... }

3.5.3 Naming Enumerations

Names of enumeration types (also called enums) in general should follow the standard type-naming rules (PascalCasing, etc.). However, there are additional guidelines that apply specifically to enums.

Images DO use a singular type name for an enumeration unless its values are bit fields.

public enum ConsoleColor {
  Black,
  Blue,
  Cyan,
  ...
}

Images DO use a plural type name for an enumeration with bit fields as values, also called flags enum.

Click here to view code image

[Flags]
public enum ConsoleModifiers {
  Alt = 1 << ʘ,
  Control = 1 << 1,
  Shift = 1 << 2,
}

Images DO NOT use an “Enum” suffix in enum type names.

For example, the following enum is badly named:

// Bad naming
public enum ColorEnum {
  ...
}

Images DO NOT use “Flag” or “Flags” suffixes in enum type names.

For example, the following enum is badly named:

// Bad naming
[Flags]
public enum ColorFlags {
  ...
}

Images DO NOT use a prefix on enumeration value names (e.g., “ad” for ADO enums, “rtf” for rich text enums).

Click here to view code image

public enum ImageMode {
  ImageModeBitmap = ʘ, // ImageMode prefix is not necessary
  ImageModeGrayscale = 1,
  ImageModeIndexed = 2,
  ImageModeRgb = 3,
}

The following naming scheme would be better:

public enum ImageMode {
  Bitmap = ʘ,
  Grayscale = 1,
  Indexed = 2,
  Rgb = 3,
}

3.6 Names of Type Members

Types are made of members: methods, properties, events, constructors, and fields. The following sections describe guidelines for naming type members.

3.6.1 Names of Methods

Because methods are the means of taking action, the design guidelines require that method names be verbs or verb phrases. Following this guideline also serves to distinguish method names from property and type names, which are noun or adjective phrases.

Images DO give methods names that are verbs or verb phrases.

public class String {
  public int CompareTo(...);
  public string[] Split(...);
  public string Trim();
}

3.6.2 Names of Properties

Unlike other members, properties should be given noun phrase or adjective names. That is because a property refers to data, and the name of the property reflects that. PascalCasing is always used for property names.

Images DO name properties using a noun, noun phrase, or adjective.

public class String {
  public int Length { get; }
}

Images DO NOT have properties that match the name of “Get” methods, such as a property named TextWriter and a method named GetTextWriter.

Click here to view code image

public string TextWriter { get {...} set {...} }
public string GetTextWriter(int value) { ... }

This pattern typically indicates that the property should really be a method. See section 5.1.3 for additional information.

Images DO name collection properties with a plural phrase describing the items in the collection instead of using a singular phrase followed by “List” or “Collection.”

Click here to view code image

public class ListView {
  // good naming
  public ItemCollection Items { get; }

  // bad naming
  public ItemCollection ItemCollection { get; }
}

Images DO name Boolean properties with an affirmative phrase (CanSeek instead of CantSeek). Optionally, you can also prefix Boolean properties with “Is,” “Can,” or “Has,” but only where it adds value.

For example, CanRead is more understandable than Readable. However, Created is actually more readable than IsCreated. Having the prefix is often too verbose and unnecessary, particularly in the face of IntelliSense in the code editors. It is just as clear to type MyObject.Enabled = and have IntelliSense give you the choice of true or false as it is to have MyObject.IsEnabled =, and the second approach is more verbose.

Images CONSIDER giving a property the same name as its type.

For example, the following property correctly gets and sets an enum value named Color, so the property is named Color:

Click here to view code image

public enum Color {...}
public class Control {
  public Color Color { get; set; }
}

3.6.3 Names of Events

Events always refer to some action, either one that is happening or one that has occurred. Therefore, as with methods, events are named with verbs, and verb tense is used to indicate the time when the event is raised.

Images DO name events with a verb or a verb phrase.

Examples include Clicked, Painting, and DroppedDown.

Images DO give events names with a concept of before and after, using the present and past tenses, such as Closing and Closed.

For example, a close event that is raised before a window is closed would be called Closing, and one that is raised after the window is closed would be called Closed.

Images DO NOT use “Before” or “After” prefixes or postfixes to indicate pre- and post-events. Use present and past tenses as just described.

Images DO name event handlers (delegates used as types of events) with the “EventHandler” suffix, such as ClickedEventHandler.

Click here to view code image

public delegate void ClickedEventHandler(object sender,
  ClickedEventArgs e);

Note that you should create custom event handlers very rarely. Instead, most APIs should simply use EventHandler<T>. Section 5.4.1 talks about event design in more detail.

Images DO use two parameters named sender and e in event handlers.

The sender parameter represents the object that raised the event. The sender parameter is typically of type object, even if it is possible to employ a more specific type. The pattern is used consistently across .NET and is described in more detail in section 5.4.

Click here to view code image

public delegate void <EventName>EventHandler(object sender,
                                             <EventName>EventArgs e);

Images DO name event argument classes with the “EventArgs” suffix, as shown in the following example:

Click here to view code image

public class ClickedEventArgs : EventArgs {
  int x;
  int y;
  public ClickedEventArgs (int x, int y) {
     this.x = x;
     this.y = y;
  }
  public int X { get { return x; } }
  public int Y { get { return y; } }
}

3.6.4 Naming Fields

The field-naming guidelines apply to static public and protected fields. Internal and private fields are not covered by guidelines, and public or protected instance fields are not allowed by the member design guidelines, which are described in Chapter 5.

Images DO use PascalCasing in field names.

Click here to view code image

public class String {
   public static readonly string Empty = "";
}
public struct UInt32 {
   public const MinValue = ʘ;
}

Images DO name fields using a noun, noun phrase, or adjective.

Images DO NOT use a prefix for public or protected field names.

For example, do not use “g_” or “s_” to indicate static fields. Publicly accessible fields (the subject of this section) are very similar to properties from the API design point of view; therefore, they should follow the same naming conventions as properties.

3.7 Naming Parameters

Beyond the obvious reason of readability, it is important to follow the guidelines for parameter names because parameters are displayed in documentation and in the designer when visual design tools provide IntelliSense and class browsing functionality.

Images DO use camelCasing in parameter names.

Click here to view code image

public class String {
   public bool Contains(string value);
   public string Remove(int startIndex, int count);
}

Images DO use descriptive parameter names.

Parameter names should be descriptive enough to use with their types to determine their meaning in most scenarios.

Images CONSIDER using names based on a parameter’s meaning rather than the parameter’s type.

Development tools generally provide useful information about the type, so the parameter name can be put to better use describing semantics rather than the type. Occasional use of type-based parameter names is entirely appropriate—but it is not ever appropriate under these guidelines to revert to the Hungarian naming convention.

3.7.1 Naming Operator Overload Parameters

This section discusses naming parameters of operator overloads.

Images DO use left and right for binary operator overload parameter names if there is no meaning to the parameters.

Click here to view code image

public static TimeSpan operator-(DateTimeOffset left,
                                 DateTimeOffset right)
public static bool operator==(DateTimeOffset left,
                              DateTimeOffset right)

Images DO use value for unary operator overload parameter names if there is no meaning to the parameters.

Click here to view code image

public static BigInteger operator-(BigInteger value);

Images CONSIDER meaningful names for operator overload parameters if doing so adds significant value.

Click here to view code image

public static BigInteger Divide(BigInteger dividend,
                                BigInteger divisor);

Images DO NOT use abbreviations or numeric indices for operator overload parameter names.

Click here to view code image

// incorrect parameter naming
public static bool operator ==(DateTimeOffset d1,
                               DateTimeOffset d2);

3.8 Naming Resources

The guidance from this section in previous editions is obsolete, and has been archived in Appendix B.

Images DO NOT directly expose localizable resources as public (or protected) members.

The types and members automatically generated by a resource editor should use the internal access modifier.

When it does make sense to expose a resource via public API, use intentional type and member design.

Summary

The naming guidelines described in this chapter, if followed, provide a consistent scheme that will make it easy for users of a framework to identify the function of elements of the framework. The guidelines provide naming consistency across frameworks developed by different organizations or companies.

The next chapter provides general guidelines for implementing types.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.195.24