In all cases, our best guidance is consistency. Keep new code and changes consistent with the style in the files. For new files, it should conform to the style for that component. Last, if there's a completely new component, anything that is reasonably broadly accepted is fine.
For C# files (*.cs, *.cshtml, *.xaml.cs), we use Pascal Case, strongly-typed, OOP guidelines. Please be aware of common patterns such as Factory, Singleton, Principle of Least Astonishment, etc.
For non code files (*.html, *.xml, *.xaml, etc), please have the non-code markup/text reference any code methods directly. I.e. A XAML/MVC event must be specified in the markup, so a developer knows what .cs code this markup calls.
For *.config files, keep custom entries to a minimum. But do include: Web service root URLs, redirect out URLs, 100% uptime connection strings (i.e. for exception log tables.)
The general rule we follow is "use Visual Studio defaults".
- We use Allman style braces, where each brace begins on a new line. A single line statement block can go without braces but the block must be properly indented on its own line and it must not be nested in other statement blocks that use braces
- We use four spaces of indentation (no tabs).
- We use
camelCaseField
for internal and private fields and usereadonly
where possible. - Use
this
andbase
when ambiguity exists. Visible references to source class is critical in code maintenance. - We always specify the scope, even if it's the default (i.e.
private string _foo
notstring _foo
). - Namespace imports should be specified at the top of the file, outside of
namespace
declarations and should be sorted alphabetically, withSystem.
namespaces at the top and blank lines between different top level groups. - Avoid more than one empty line at any time. For example, do not have two blank lines between members of a type.
- Avoid spurious free spaces.
For example avoid
if (someVar == 0)...
, where the dots mark the spurious free spaces. Consider enabling "View White Space (Ctrl+E, S)" if using Visual Studio, to aid detection. - If a file happens to differ in style from these guidelines (e.g. private members are named
m_member
rather than_member
), the existing style in that file takes precedence. - Use consise conventions. I.e. use
var
when it's obvious what the variable type is (i.e.var stream = new FileStream(...)
notvar stream = OpenStandardInput()
). - We use BCL types instead of language-specific type aliases (i.e.
Int32, String, Boolean
instead ofint, string, bool
, etc) for both type references as well as method calls - We use PascalCasing to name all our constant local variables. The only exception is for interop code where the constant value should exactly match the name and value of the code you are calling via interop.
ObservableLinkedList`1.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using Microsoft.Win32;
namespace System.Collections.Generic
{
public partial class ObservableLinkedList<T> : INotifyCollectionChanged, INotifyPropertyChanged
{
private ObservableLinkedListNode<T> headField;
private int countField;
public ObservableLinkedList(IEnumerable<T> items)
{
if (items == null)
throw new ArgumentException("items");
foreach (T item in items)
{
AddLast(item);
}
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public int Count
{
get { return countField; }
}
public ObservableLinkedListNode AddLast(T value)
{
var newNode = new LinkedListNode<T>(this, value);
InsertNodeBefore(headField, node);
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler handler = CollectionChanged;
if (handler != null)
{
handler(this, e);
}
}
private void InsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
...
}
...
}
}