C# Coding standards
- use PascalCasing for class names and method names
public class ClientActivity
{
public void ClearStatistics()
{
//...
}
public void CalculateStatistics()
{
//...
}
}
- use camelCasing for method arguments and local variables.
public class UserLog
{
public void Add(LogEvent logEvent)
{
var itemCount = logEvent.Items.Count;
// ...
}
}
- do not use Hungarian notation or any other type identification in identifiers (except interfaces)
// Correct
int counter;
string name;
// Avoid
int iCounter;
string strName;
The Visual Studio IDE makes determining types very easy (via tooltips). In general you want to avoid type indicators in any identifier (Exception: Interfaces)
- do not use SCREAMING CAPS for constants or read-only variables
// Correct
public static const string ShippingType = "DropShip";
// Avoid
public static const string SHIPPINGTYPE = "DropShip";
- avoid using Abbreviations. Exceptions: abbreviations commonly used as names, such as Id, Xml, Ftp, Uri
/ Correct
UserGroup userGroup;
Assignment employeeAssignment;
// Avoid
UserGroup usrGrp;
Assignment empAssignment;
// Exceptions
CustomerId customerId;
XmlDocument xmlDocument;
FtpHelper ftpHelper;
UriPart uriPart;
- use PascalCasing for abbreviations 3 characters or more (2 chars are both uppercase)
HtmlHelper htmlHelper;
FtpTransfer ftpTransfer;
UIControl uiControl;
The type here is Pascal, but the field is camelNotation.
- do not use Underscores in identifiers. Prefix private member variables with an underscore.
// Correct
public DateTime clientAppointment;
public TimeSpan timeLeft;
// Avoid
public DateTime client_Appointment;
public TimeSpan time_Left;
// Exception
private DateTime registrationDateStore;
- use predefined type names instead of system type names like Int16, Single, UInt64, etc.
// Correct
string firstName;
int lastIndex;
bool isSaved;
// Avoid
String firstName;
Int32 lastIndex;
Boolean isSaved;
- use implicit type var for local variable declarations
var stream = File.Create(path);
var customers = new Dictionary();
var index = 100;
var greeting = "hello";
var isCompleted = true;
- prefix interfaces with the letter I. Interface names are noun (phrases) or adjectives
public interface IShape
{
}
public interface IGroupable
{
}
- name source files according to their main classes
// Located in Task.cs
public partial class Task
{
//...
}
- organize namespaces with a clearly defined structure. Generally namespaces should reflect the folder hierarchy within a project
- vertically align curly braces
class Program
{
static void Main(string[] args)
{
}
}
- declare all member variables at the top of a class, with static variables at the very top. Exception, keep backing variables with their property.
public class Account
{
private int AgeStore;
private string NameStore;
public string Number {get; set;}
// Constructor
public Account()
{
// ...
}
}
- use singular names for enums and plural for bit field enums.
// Correct
public enum Color
{
Red,
Green,
Blue,
Yellow,
Magenta,
Cyan
}
// Exception
[Flags]
public enum Dockings
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}
- do not explicitly specify a type of an enum or values of enums (except bit fields and where the value is required)
// Don't
public enum Direction : long
{
North = 1,
East = 2,
South = 3,
West = 4
}
// Correct
public enum Direction
{
North,
East,
South,
West
}
// Correct
public enum Temperatures
{
Freezing = 32,
Boiling = 212
}
// Exception
[Flags]
enum Days
{
None = 0b_0000_0000, // 0
Sunday = 0b_0000_0001, // 1
Monday = 0b_0000_0010, // 2
Tuesday = 0b_0000_0100, // 4
Wednesday = 0b_0000_1000, // 8
Thursday = 0b_0001_0000, // 16
Friday = 0b_0010_0000, // 32
Saturday = 0b_0100_0000 // 64
}
class MyClass
{
Days meetingDays = Days.Tuesday | Days.Thursday;
}
- Name global styles and static resources with their functional purpose instead of (for example) a color name
// Don't
<Application.Resources>
<ResourceDictionary>
<Color x:Key="Red">#FFDC0A0A</Color>
</ResourceDictionary>
</Application.Resources>
//Correct
<Application.Resources>
<ResourceDictionary>
<Color x:Key="Error">#FFDC0A0A</Color>
</ResourceDictionary>
</Application.Resources>
- If your line of code is greater than 80, chop it to two or more lines except where essential.
- Prefer Switch statements to multiple nested if statements
// Don't
if (...)
{
if (...)
{
...
}
}
else if(...)
{
...
}
// Correct
switch(...)
case 1:
...
break;
case 2:
...
Break;
- Use braces with conditionals, for loops, etc.
// Correct
if (condition)
{
action;
}
// Don't
if(conditioin)
action;
- Where possible prefer switch expressions over switch statements
// wrong
switch(foo)
{
case 1:
x = 50;
break;
case 2:
x = 100
break;
default:
x = 0;
break
}
// Correct
foo switch
{
1 => 50;
2 => 100;
_ => 0;
}
- enable nullable references and treat these warnings as errors
#nullable enable
Person? person; //etc.
- use null conditional (?.) operator rather than if statements for null
// wrong
if (a != null)
{
if (b != null)
{
return c.name;
}
}
// right
return a?.b?.c.name;
- use null coalescing (??) operator rather than if statements for null
// wrong
if (a != null)
{
if (b != null)
{
return c.name;
}
{
else return string.empty;
}
}
else
{
return string.empty;
}
// right
return a?.b?.c.name ?? string.empty;
- refer SetValue & Lambda expressions for properties (inherit from BaseViewModel)
// wrong
private string _property;
public string Property
{
get { return _property; }
set
{
_property = value;
OnPropertyChanged;
}
}
// right
private string _property;
public string Property
{
get => _property;
set => SetValue(ref _property, value);
}
// SetValue is created in the base class and handles checking for changed values and calls to INotifyPropertyChanged.
- declare and define commands in one statement in the ViewModel
public ICommand MyCommand =>
new Command( async ( ) => await OnMyCommand( ) )
- Do not place all backing variables together — put them with their properties
// Wrong
private string _prop1;
private int _prop2;
private int _prop3;
public string Prop1
{ ... }
public int Prop2
{...}
public int Prop3
{...}
// Correct
private string _prop1;
public string Prop1
{ ... }
private int _prop2;
public int Prop2
{...}
private int _prop3;
public int Prop3
{...}
- Treat Warnings As Errors
- Use “TODO” sparingly, and check the TODO list often