-
Notifications
You must be signed in to change notification settings - Fork 6
Coding Conventions
Robin Sedlaczek edited this page Aug 8, 2016
·
3 revisions
For non code files (xml etc) our current best guidance is consistency. When editing files, 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.
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 (See issue 381 for examples).
- We use four spaces of indentation (no tabs).
- We use
_camelCasefor internal and private fields and usereadonlywhere possible. Prefix instance fields with_, static fields withs_and thread static fields witht_. When used on static fields,readonlyshould come afterstatic(i.e.static readonlynotreadonly static). - We avoid
this.unless absolutely necessary. - We always specify the visibility, even if it's the default (i.e.
private string _foonotstring _foo). Visibility should be the first modifier (i.e.public abstractnotabstract public). - Namespace imports should be specified at the top of the file, outside of
namespacedeclarations and should be sorted alphabetically. - 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_memberrather than_member), the existing style in that file takes precedence. - We use
varwhen it's obvious what the variable type is (i.e.var stream = new FileStream(...)notvar stream = OpenStandardInput()). - We use language keywords instead of BCL types (i.e.
int, string, floatinstead ofInt32, String, Single, etc) for both type references as well as method calls (i.e.int.Parseinstead ofInt32.Parse). - We use PascalCasing to name all our constant local variables and fields. 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.
- We use
nameof(...)instead of"..."whenever possible and relevant. - Use plain code to validate parameters at public boundaries. Do not use Contracts or magic helpers.
if (argument == null)
{
throw new ArgumentNullException("argument");
}
- Use Debug.Assert() for checks not needed in retail builds. Always include a “message” string in your assert to identify failure conditions. Add assertions to document assumptions on non-local program state or parameter values, e.g. “At this point in parsing the scanner should have been advanced to a ‘.’ token by the caller”.
We also use the .NET Codeformatter Tool to ensure the code base maintains a consistent style over time, the tool automatically fixes the code base to conform to the guidelines outlined above.
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> _head;
private int _count;
public ObservableLinkedList(IEnumerable<T> items)
{
if (items == null)
throw new ArgumentNullException(nameof(items));
foreach (T item in items)
{
AddLast(item);
}
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public int Count
{
get { return _count; }
}
public ObservableLinkedListNode AddLast(T value)
{
var newNode = new LinkedListNode<T>(this, value);
InsertNodeBefore(_head, 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)
{
...
}
...
}
}ObservableLinkedList`1.ObservableLinkedListNode.cs:
using System;
namespace System.Collections.Generics
{
partial class ObservableLinkedList<T>
{
public class ObservableLinkedListNode
{
private readonly ObservableLinkedList<T> _parent;
private readonly T _value;
internal ObservableLinkedListNode(ObservableLinkedList<T> parent, T value)
{
Debug.Assert(parent != null);
_parent = parent;
_value = value;
}
public T Value
{
get { return _value; }
}
}
...
}
}