Naming Conventions for .NET / C# Projects

Martin Zahn, Akadia AG, 20.03.2003


The original of this document was developed by the Microsoft special interest group. We made some addons.

This document explains the naming conventions that should be used with .NET projects.

A consistent naming pattern is one of the most important elements of predictability and discoverability in a managed class library. Widespread use and understanding of these naming guidelines should eliminate unclear code and make it easier for developers to understand shared code.

Capitalization Styles Defined

We define three types of capitalization styles:

Pascal case

The first letter in the identifier and the first letter of each subsequent concatenated word are capitalized.

Example:

BackColor, DataSet

Camel case

The first letter of an identifier is lowercase and the first letter of each subsequent concatenated word is capitalized.

Example:

numberOfDays, isValid

Uppercase

All letters in the identifier are capitalized.

Example:

ID, PI

Hungarian Type Notation Defined

Hungarian notation is any of a variety of standards for organizing a computer program by selecting a schema for naming your variables so that their type is readily available to someone familiar with the notation. It is in fact a commenting technique.

Example:

strFirstName, iNumberOfDays

There are different opinions about using this kind of type notation in programming nowadays. Some say that it’s useful, and it should be used everywhere to enhance clarity of your code. Others say it just obfuscates your code, because it has no real advantage in modern programming environments.

Our point of view is a moderated one: use it wisely, meaning, we only use Hungarian notation for private or local variables, that are only accessible and interesting to the programmer of the class.

Don’t use it with public variables, properties or parameters in methods, because they are exposed to the outside world. Someone who uses your classes and accesses properties of your class, is not interested in type, but just wants to use them.

In the .NET framework, there are a lot of types, so we extended and adapted the Hungarian notation with our own type notation.

Naming Guidelines

1).  Private Variables (Fields in C#) Naming Guidelines

Naming guidelines

Prefix private variables with a "_" and Hungarian-style notation.

Case guidelines

Use camel case as a general rule, or uppercase for very small words

Example:

_strFirstName, _dsetEmployees

// Field
private OleDbConnection
_connection;

// Property
public OleDbConnection Connection
{
  get { return
_connection; }
  set {
_connection = value; }
}

2).  Local Variables Naming Guidelines

Naming guidelines

Prefix private or local variables with Hungarian-style notation.

Case guidelines

Use camel case as a general rule, or uppercase for very small words

Example:

strFirstName, dsetEmployees

3).  Namespace Naming Guidelines

Naming guidelines

The general rule for naming namespaces is to use the company name followed by the technology name and optionally the feature and design as follows:

CompanyName.TechnologyName[.Feature][.Design]

Prefixing namespace names with a company name or other well-established brand avoids the possibility of two published namespaces having the same name. Use a stable, recognized technology name at the second level of a hierarchical name.

Example:

Akadia.Traffic, System.Web.UI, System.Windows.Forms

Case guidelines

Use Pascal case as a general rule, or uppercase for very small words.

Example:

System.Windows.Forms, System.Web.UI

4).  Class Naming Guidelines

Naming guidelines

Use a noun or noun phrase to name a class.
Do not use a type prefix, such as C for class, on a class name.
Do not use the underscore character (_).

Case guidelines

Use Pascal case. Example:

FileStream, Button

5).  Interface Naming Guidelines

Naming guidelines

Prefix interface names with the letter "I", to indicate that the type is an interface.
Do not use the underscore character (_).

Case guidelines

Use Pascal case. Example:

IServiceProvider, IFormatable

6).  Parameter Naming Guidelines

Naming guidelines

Use descriptive parameter names. Parameter names should be descriptive enough that the name of the parameter and its type can be used to determine its meaning in most scenarios. To distinguish parameters from other variables the prefix "p" should be used.

Do not prefix parameter names with Hungarian type notation.

Do not use a prefix for parameter names of an event handler and exceptions.

Case guidelines

Use camel case. Example:

pTypeName, pNumberOfItems

7).  Method Naming Guidelines

Naming guidelines

Use verbs or verb phrases to name methods.

Case guidelines

Use Pascal case. Example:

RemoveAll(), GetCharAt()

8).  Property / Enumerations Naming Guidelines

Naming guidelines

Use a noun or noun phrase to name properties.
Do not use Hungarian notation.

Case guidelines

Use Pascal case. Example:

BackColor, NumberOfItems

9).  Event Naming Guidelines

Naming guidelines

Use an EventHandler suffix on event handler names.

Specify two parameters named sender and e. The sender parameter represents the object that raised the event. The sender parameter is always of type object, even if it is possible to use a more specific type. The state associated with the event is encapsulated in an instance of an event class named "e". Use an appropriate and specific event class for the e parameter type.

Name an event argument class with the EventArgs suffix.

Case guidelines

Use Pascal case. Example:

public delegate void MouseEventHandler(object sender, MouseEventArgs e);

9).  Exception Naming Guidelines

Naming guidelines

Event handlers in Visual Studio .NET tend to use an "e" parameter for the event parameter to the call. To ensure we avoid a conflict, we will use "ex" as a standard variable name for an Exception object.

Example

catch (Exception ex)
{
  // Handle Exception
}

10).   Constant Naming Guidelines

The names of variables declared class constants should be all uppercase with words separated by underscores. It is recommended to use a grouping naming schema.

Example (for group AP_WIN):

AP_WIN_MIN_WIDTH, AP_WIN_MAX_WIDTH, AP_WIN_MIN_HIGHT, AP_WIN_MAX_HIGHT

11). C# Primitive Type Notation

sbyte   sy
short   s
int     i
long    l
byte    y
ushort  us
uint    ui
ulong   ul
float   f
double  d
decimal dec
bool    b
char    c

12).  Visual Control Type Notation

Assembly                                asm
Boolean                                 bln
Button                                  btn
Char                                    ch
CheckBox                                cbx
ComboBox                                cmb
Container                               ctr
DataColumn                              dcol
DataGrid                                dgrid
DataGridDateTimePickerColumn            dgdtpc
DataGridTableStyle                      dgts
DataGridTextBoxColumn                   dgtbc
DataReader                              dreader
DataRow                                 drow
DataSet                                 dset
DataTable                               dtable
DateTime                                date
Dialog                                  dialog
DialogResult                            dr
Double                                  dbl
Exception                               ex
GroupBox                                gbx
HashTable                               htbl
ImageList                               iml
Integer                                 int
Label                                   lbl
ListBox                                 lbx
ListView                                lv
MarshallByRefObject                     rmt
Mainmenu                                mm
MenuItem                                mi
MDI-Frame                               frame
MDI-Sheet                               sheet
NumericUpDown                           nud
Panel                                   pnl
PictureBox                              pbx
RadioButton                             rbtn
SDI-Form                                form
SqlCommand                              sqlcom
SqlCommandBuilder                       sqlcomb
SqlConnection                           sqlcon
SqlDataAdapter                          sqlda
StatusBar                               stb
String                                  str
StringBuilder                           strb
TabControl                              tabctrl
TabPage                                 tabpage
TextBox                                 tbx
ToolBar                                 tbr
ToolBarButton                           tbb
Timer                                   tmr
UserControl                             usr
WindowsPrincipal                        wpl

 

 

Type

Standard / Convention

Example

Namespaces

Standard Based Upon Microsoft .NET Library Standards

Pascal Case, no underscores. Use CompanyName.TechnologyName as root. If you don't have a company, use your domain name or your own initials. Note that any acronyms of three or more letters should be pascal case (Xml instead of XML) instead of all caps.

Why: This convention is consistent with the .NET Framework and is easy to read.

AppliedIS.TimeCard.BusinessRules
IrritatedVowel.Controllers
PeteBrown.DotNetTraining.InheritanceDemo PeteBrown.DotNetTraining.Xml

Assemblies

Standard Based Upon Microsoft .NET Library Standards

If the assembly contains a single name space, or has an entire self-contained root namespace, name the assembly the same name as the namespace.

Why: This convention is consistent with the .NET Framework and is easy to read. More importantly, however, it keeps your assembly names and namespaces lined up, making it really easy to figure out what is any particular assembly, and what assembly you need to reference for any given class.

AppliedIS.TimeCard.BusinessRules.dll
IrritatedVowel.Controllers.dll

Classes and Structs

Standard Based Upon Microsoft .NET Library Standards

Pascal Case, no underscores or leading "C" or "cls". Classes may begin with an "I" only if the letter following the I is not capitalized, otherwise it looks like an Interface. Classes should not have the same name as the namespace in which they reside. Any acronyms of three or more letters should be pascal case, not all caps. Try to avoid abbreviations, and try to always use nouns.

Why: This convention is consistent with the .NET Framework and is easy to read.

Widget
InstanceManager
XmlDocument
MainForm
DocumentForm
HeaderControl
CustomerListDataSet (typed dataset) 

Collection Classes

Standard Based Upon Microsoft .NET Library Standards

Follow class naming conventions, but add Collection to the end of the name

Why: This convention is consistent with the .NET Framework and is easy to read.

WidgetCollection

Delegate Classes

Standard Based Upon Microsoft .NET Library Standards

Follow class naming conventions, but add Delegate to the end of the name

Why: This convention is consistent with the .NET Framework and is easy to read.

WidgetCallbackDelegate

Exception Classes

Standard Based Upon Microsoft .NET Library Standards

Follow class naming conventions, but add Exception to the end of the name

Why: This convention is consistent with the .NET Framework and is easy to read.

InvalidTransactionException

Attribute Classes

Standard Based Upon Microsoft .NET Library Standards

Follow class naming conventions, but add Attribute to the end of the name

Why: This convention is consistent with the .NET Framework and is easy to read.

WebServiceAttribute

Interfaces

Standard Based Upon Microsoft .NET Library Standards

Follow class naming conventions, but start the name with "I" and capitalize the letter following the "I"

Why: This convention is consistent with the .NET Framework and is easy to read. It also distinguishes classes from interfaces, where (unlike in VB6) are truly different beings. This avoid name collisions as well, as it is quite common to have IFoo and a class named Foo that implements IFoo.

IWidget

Enumerations

Standard Based Upon Microsoft .NET Library Standards

Follow class naming conventions. Do not add "Enum" to the end of the enumeration name. If the enumeration represents a set of bitwise flags, end the name with a plural.

Why: This convention is consistent with the .NET Framework and is easy to read.

SearchOptions (bitwise flags)

AcceptRejectRule (normal enum)

Functions and Subs

Standard Based Upon Microsoft .NET Library Standards

Pascal Case, no underscores except in the event handlers. Try to avoid abbreviations. Many programmers have a nasty habit of overly abbreviating everything. This should be discouraged. We're not designing license plates or being charged by the letter :)

Functions and subs must differ by more than case to be usable from case-insensitive languages like Visual Basic .NET

Why: This convention is consistent with the .NET Framework and is easy to read.

VB: Public Sub DoSomething(...)

C#: public void DoSomething(...)

Properties and Public * Member Variables

Standard Based Upon Microsoft .NET Library Standards

Pascal Case, no underscores. Try to avoid abbreviations. Members must differ by more than case to be usable from case-insensitive languages like Visual Basic .NET.

Why: This convention is consistent with the .NET Framework and is easy to read.

VB: Public Property RecordId As Integer

C#: public int RecordId

Parameters

Standard Based Upon Microsoft .NET Library Standards

Camel Case. Try to avoid abbreviations. Parameters must differ by more than case to be usable from case-insensitive languages like Visual Basic .NET.

Why: This convention is consistent with the .NET Framework and is easy to read.

VB: ByRef recordId As Integer

C#: ref int recordId

Procedure-Level Variables

Standard Based Upon De facto Industry-Accepted Practices

Camel Case

Why: This convention is consistent with the .NET Framework and is easy to read. It also avoids naming collisions with class-level variables (see below)

VB: Dim recordId As Integer

C#: int recordId ;

Class-Level Private and Protected Variables

Standard Based Upon De facto Industry-Accepted Practices

Camel Case with Leading Underscore. In VB.NET, always indicate "Protected" or "Private", do not use "Dim". Use of "m_" is discouraged, as is use of a variable name that differs from the property by only case, especially with protected variables as that violates compliance, and will make your life a pain if you program in VB.NET, as you would have to name your members something different from the accessor/mutator properties.

Of all the items here, the leading underscore is really the only controversial one. I personally prefer it over straight underscore-less camel case for my private variables so that I don't have to qualify variable names with "this." to distinguish from parameters in constructors or elsewhere where I likely will have a naming collision. With VB.NET's case insensitivity, this is even more important as your accessor properties will usually have the same name as your private member variables except for the underscore.

As far as m_ goes, it is really just about aesthetics. I (and many others) find m_ ugly, as it looks like there is a hole in the variable name. It's almost offensive. I used to use it in VB6 all the time, but that was only because variables could not have a leading underscore. I couldn't be happier to see it go away.

Microsoft recommends against the m_ (and the straight _) even though they did both in their code. Also, prefixing with a straight "m" is right out. Of course, since they code mainly in C#, they can have private members that differ only in case from the properties. VB folks have to do something else. Rather than try and come up with language-by-language special cases, I recommend the leading underscore for all languages that will support it.

If I want my class to be fully CLS-compliant, I could leave off the prefix on any C# protected member variables. In practice, however, I never worry about this as I keep all potentially protected member variables private, and supply protected accessors and mutators instead.

Why: In a nutshell, this convention is simple (one character), easy to read (your eye is not distracted by other leading characters), and successfully avoids naming collisions with procedure-level variables and class-level properties.

VB: Private _recordId As Integer

C#: private int _recordId ;

Controls on Forms

An Extension to the Standards

May 2009 update

Note that I still consider this useful in many respects, especially for intellisense grouping, but have backed away from using this in recent projects, specifically Silverlight and WPF. I still use an appropriate classification suffix such as Field or Label (but not an actual control type) so that I can differentiate between, say, the last name field and the label for it.

Examples would be LastNameField, LastNameLabel, NextPageNavigation, PreviousPageNavigation. The classifications you pick will need to make sense to you, and also allow for signficiant flexibility for the designer of the UI to change the control type in Xaml without you having to change the name in the storyboards (runtime checked), code behind (compile-time checked), and control lookups in code behind (runtime checked).

I backed away simply because it didn't look right in generated member variables in my applications, or in the x:Name properties in Xaml. It was a code smell issue, albeit a minor one.

Note also that in Silverlight and WPF, I only name controls which need to be named because they are used in the code behind or are referred to from a storyboard or relative binding. The name is the primary contract between the code and the visual design, and you want to keep that contract as small as possible.

Note that I have seen the "ux" prefix in example code on the net, and from Microsoft. Some folks still find it useful. You'll need to make that decision for yourself.

Original Information from 2002

In recent projects (since 2002 or so), I have taken to a single prefix for all my UI controls. I typically use "ux" (I used to use "ui", but it wasn't set apart well in intellisense). "ux" comes from my usual design abbreviations where it means "User eXperience", which has also since become a popular acronym. I have found this to be extremely helpful in that I get the desired grouping in the intellisense even better than if I use "txt", "lbl" etc. It also allows you to change combo boxes to text boxes etc. without having to change the names - something that happens often during initial prototyping, or when programming using highly iterative agile/xp methodologies.

Why: This convention avoids problems with changing control types (textboxes to drop-down lists, or simple text box to some uber textbox, or text box to date picker, for example), and groups the items together in intellisense. It is also much shorter than most Hungarian conventions, and definitely shorter and less type-dependent than appending the control type to the end of the variable name. I will use generic suffixes which allow me enough freedom to change them around.

"ux" prefix

uxUserIdField, uxHeaderLabel, uxPatientDateOfBirthField, uxSubmitCommand

no "ux" prefix

LastNameField, LastNameLabel, SubmitCommand, NextPageNavigation

Constants

Standard Based Upon Microsoft .NET Library Standards

Same naming conventions as public/private member variables or procedure variables of the same scope. If exposed publicly from a class, use PascalCase. If private to a function/sub, use camelCase..

Do not use SCREAMING_CAPS

Why: This convention is consistent with the .NET Framework and is easy to read. A sizable section of the Framework Design Guidelines is dedicated to why they chose not to go the SCREAMING_CAPS route. Using SCREAMING_CAPS also exposes more of the implementation than is necessary. Why should a consumer need to know if you have an enum, or (perhaps because they are strings) a class exposing public constants? In the end, you often want to treat them the same way, and black-box the implementation. This convention satisfies that criteria.