##Naming Convetions and Style
- Use Pascal casing for type and method names
public class SomeClass
{
const int DefaultSize = 100;
public void SomeMethod()
{
}
}- Use camel casing for local variable names and method arguments
void SomeMethod(int someNumber)
{
int number;
}- Prefix interface names with I
interface IMyInterface
{
}-
Avoid using Hungarian notation
-
Use
thisif you want to distinguish member variables with local -
Suffix custom attribute classes with
Attribute -
Suffix custom exception classes with
Exception -
Name methods using verb-object-pair, such as
ShowDialog() -
Methods with return values should have a name describing the value returned, such as
GetObjectState() -
Use descriptive variable names a) Avoid single character variable names, such as i or t. Use
indexortempinstead b) Do not abbreviate words (such asnuminstead ofnumber) -
Always use C# predefined types rather than the aliases in the
Systemnamespace when declaring local variable, class field or method argument. But use types fromSystemnamespace when using static members
// Avoid
Object myObject;
String myString;
Int32 myNumber;
string.Empty
int.MaxValue
string.IsNullOrEmpty()
// Correct
object myObject;
string myString;
int myNumber;
String.Empty
Int32.MaxValue
String.IsNullOrEmpty() - With generics, use capital letters for types. Reserve suffixing Type when dealing with the .Net type
Type
// Avoid
public class LinkedList<KeyType,DataType>
{
}
// Correct
public class LinkedList<K, T>
{
}-
Use meaningful namespaces such as the product name or the company name
-
Avoid fully qualified type names. Use the
usingstatement -
Avoid putting a
usingstatement inside a namespace -
Group all framework namespaces together and put custom or third-party namespaces underneath
// Avoid
using MyCompany;
using MyControls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
// Correct
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;- Use delegate inference instead of explicit delegate instantiation
public delegate void ImageChangedDelegate();
public void ChangeImage()
{
}
// Avoid
ImageChangedDelegate imageChanged = new ImageChangedDelegate(ChangeImage);
// Correct
ImageChangedDelegate imageChanged = ChangeImage;-
Indent comments at the same level of indentation as the code you are documenting
-
All comments should pass spell checking. Misspelled comments indicate sloppy development.
-
All member variables should be declared at the top, with one line separating them from the properties or methods
public class MyClass
{
int number;
string name;
public void SomeMethod1()
{
}
public void SomeMethod2()
{
}
}-
Declare a local variable as close as possible to its first use.
-
A file name should reflect the class it contains.
-
When using partial types and allocating a part per file, name each file after the logical part that part plays
// In MyClass.cs
public partial class MyClass
{
}
// In MyClass.Designer.cs
public partial class MyClass
{
}-
Always place an open curly brace
{in a new line. -
With anonymous methods, mimic the code layout of a regular method, aligned with the delegate declaration. (complies with placing an open curly brace in a new line)
delegate void SomeDelegate(string someString);
// Avoid
void InvokeMethod()
{
SomeDelegate someDelegate = delegate(string message) {MessageBox.Show(message);};
someDelegate("Hello");
}
// Correct
void InvokeMethod()
{
SomeDelegate someDelegate = delegate(string message)
{
MessageBox.Show(message);
};
someDelegate("Hello");
}- Use empty parantheses on parameter-less anonymous methods.Omit the parentheses only if the anonymous method could have been used on any delegate;
delegate void SomeDelegate();
// Avoid
SomeDelegate someDelegate = delegate
{
MessageBox.Show("Hello");
};
// Correct
SomeDelegate someDelegate = delegate()
{
MessageBox.Show("Hello");
}- With Lambda expressions, mimic the code layout of a regular method, aligned with the delegate declaration. Omit the variable type and rely on type inference, yet use parentheses:
delegate void SomeDelegate(string someString);
// Avoid
SomeDelegate someDelegate = (string message) =>
{
Trace.WriteLine(message);
MessageBox.Show(message);
};
// Correct
SomeDelegate someDelegate = (message) =>
{
Trace.WriteLine(message);
MessageBox.Show(message);
};- Only use in-line Lambda expressions when they contain a single simple statement. Avoid multiple statements that require a curly brace or a
returnstatement with in-line expressions. Omit parentheses:
delegate void SomeDelegate(string someString);
void MyMethod(SomeDelegate someDelegate)
{
}
// Avoid
MyMethod((message) => {Trace.WriteLine(message);MessageBox.Show(message);});
// Correct
MyMethod(message => MessageBox.Show(message));-
Avoid putting multiple classes in a single file
-
A single file should contribute types to only a single namespace. Avoid having multiple namespaces in the same file
-
Avoid files with more than 500 lines (excluding machine-generated code)
-
Avoid methods with more than 50 lines
-
Avoid methods with more than 5 arguments
-
Lines should not exceed 120 characters
-
Do not manually edit any machine-generated code a) If modifying machine generated code, modify the format and style to match this coding standard
-
Avoid comments that explaing the obvious. Code should be self-explanatory. Good code with readable variable and method names should not require comments
-
Document only operational assumptions, alogrithm insights and so on
-
Avoid method-level documentation. Use method-level comments only as a tool tips for other developers.
-
In general, prefer overloading to default parameters:
// Avoid
class MyClass
{
void SomeMethod(int number = 123)
{
}
}
// Correct
class MyClass
{
void SomeMethod()
{
SomeMethod(123);
}
void SomeMethod(int number)
{
}
}- When using default parameters, restrict them to natural immutable constants such as null, false, or 0:
void SomeMethod(int number = 0)
{
}
void SomeMethod(string message = null)
{
}
void SomeMethod(bool flag = false)
{
}- Assert every assumption. On average, every 6th line is an assertion
using System.Diagnostics;
object GetObject()
{
}
object someObject = GetObject();
Debug.Assert(someObject != null);-
Every line of code should be walked through in a "white box" testing manner
-
Catch only exceptions for which you have explicit handling
-
In a
catchstatement that throws exceptions, always throw the original exception (or another exception constructed from the original exception) to maintain the stack location of the original error
catch(Exception ex)
{
MessageBox.Show(ex.Message);
throw;
}-
Avoid error codes as method return values
-
Avoid defining custom exception classes
-
When defining custom exception: a) Derive the custom exception from
Exceptionb) Provide custom serialization -
Avoid multiple
Main()methods in a single assembly -
Make only the most necessary types public, mark others as
internal -
Avoid code that relies on an assembly running from a particular location
-
Minimize code in application assemblies(EXE client assemblies). Use class libraries instead to contain business logical
-
Avoid providing explicit values for enums unless they are integer powers of 2:
// Avoid
public enum Color
{
Red = 1,
Green = 2,
Blue = 3
}
// Correct
public enum Color
{
Red,
Green,
Blue
}- Avoid specifying a type for an enum
// Avoid
public enum Color : long
{
Red,
Green,
Blue
}-
Always use a curly brace scope in an
ifstatement, even if it conditions a single statement -
Avoid using the ternary conditional operator
-
Always use zero-based arrays
-
With indexed collection, use zero-based indexes
-
Always explicitly initialize an array of reference types using a
forloop
public class MyClass
{
}
const int ArraySize = 100;
MyClass[] someArray = new MyClass[ArraySize];
for(int index = 0; index < someArray.Length; index++)
{
array[index] = new MyClass();
}-
Do not provide public or protected member variables. Use properties instead
-
Avoid explicit properties that do nothing except access a member variable. Use automatic properties instead:
// Avoid
class MyClass
{
int number;
public int Number
{
get
{
return number;
}
set
{
number = value;
}
}
}
// Correct
class MyClass
{
public int Number { get; set; }
}-
Avoid using the
newinheritance qualifier. Useoverrideinstead -
When override
Equals, overrideGetHashCodetoo -
Never use unsafe code, except when using interop
-
Avoid explicit casting. Use the
asoperator to defensively cast to a type
// Avoid
Dog dog = new GermanShepherd();
GermanShepherd shepherd = (GermanShepherd)dog;
// Correct
Dog dog = new GermanShepherd();
GermanShepherd shepherd = dog as GermanShepherd;
if (shepherd != null)
{
}-
Always check a delegate for
nullbefore invoking it -
Never hardcode string that will be presented to end users. Use resources instead
-
Never hardcode strings that might change based on deployment such as connection strings
-
Use
String.Emptyinstead of ""
// Avoid
string myString = "";
// Correct
string myString = String.Empty;-
Never use
goto -
Always have a
defaultcase in aswitchstatement -
Always run code unchecked by default (for the sake of performance), but explicitly in checked mode for overflow- or underflow-prone operations
int CalcPower(int number, int power)
{
result = 1;
for(int count = 1; count <= power; count++)
{
checked
{
result *= number;
}
}
return result;
}