Our overarching goals are conciseness, readability and simplicity.
On the whole, naming should follow C# standards.
Namespaces are all PascalCase, multiple words concatenated together, without hyphens ( - ) or underscores ( _ ). Namespaces should not follow reverse domain conventions as is common in Java:
BAD:
com.willowtree.project.component
GOOD:
WillowTree.Project.Component
Written in PascalCase. For example RadialSlider
.
Names of enumeration types (also called enums) in general should follow the standard type-naming rules (PascalCasing, etc.).
Enum type names should also use a singular type.
Enum type names types should not include an "Enum", "Flag", or "Flags" suffix.
Enum values should not include a prefix that references the name of the enumeration type.
BAD:
public enum Cases
{
CaseFirst,
CaseSecond
}
GOOD:
public enum Case
{
First,
Second
}
Methods are written in PascalCase. For example DoSomething()
.
All private and internal fields (including backing fields) are written with a preceding underscore in camelCase. All Properties are written in PascalCase.
Fields should use explicit access modifiers (public, private) even if they are using the default access modifier.
Public and protected fields should be avoided in favor of properties.
BAD:
public class MyClass
{
private int myPrivateVariable;
public int publicField;
int internalField;
}
GOOD:
public class MyClass
{
public int PublicField { get; set; }
private int _packagePrivate;
private int _myBackedProperty;
public int MyBackedProperty
{
get { return _myBackedProperty; }
set { _myBackedProperty = value; }
}
protected int MyProtected { get; set; }
}
The one exception to this is if you are working with Unity. These standards go against Unity convention, and you should feel free to ignore them in that case.
Static fields are the exception and should be written in PascalCase.
public static readonly int TheAnswer = 42;
Parameters are written in camelCase.
BAD:
void doSomething(Vector3 Location)
GOOD:
void DoSomething(Vector3 location)
Single character values are to be avoided except for temporary looping variables and for EventArgs parameters.
Delegates are written in PascalCase.
When declaring delegates, DO add the suffix EventHandler to names of delegates that are used in events.
By converntion, .NET event handlers always take 2 parameters: a sender and an EventArgs derived class. You should follow this convention when declaring event handlers.
BAD:
public delegate void Click()
GOOD:
public delegate void ClickEventHandler(object sender, EventArgs e)
DO add the suffix Callback to names of delegates other than those used as event handlers.
BAD:
public delegate void Render()
GOOD:
public delegate void RenderCallback()
In most cases it may be better to use Action or Func for these over explicity declared callbacks.
Following Microsoft's naming conventions on events:
- DO name events with a verb or a verb phrase.
- DO give events names with a concept of before and after, using the present and past tenses. For example, a close event that is raised before a window is closed would be called Closing, and one that is raised after the window is closed would be called Closed.
- DO NOT use "Before" or "After" prefixes or postfixes to indicate pre- and post-events. Use present and past tenses as just described.
- DO name event argument classes with the "EventArgs" suffix
- DO NOT prefix events with On. This should be reserved for protected virtual methods used to raise events.
BAD:
public event CloseCallback OnClose;
GOOD:
public event ClosedEventHandler Closed;
- DO NOT Use anonymous delegate to subscribe to events in Xamarin. This can cause memory leaks you are unable to unregister from the event (and the anonymous delegate strong captures 'this')
- DO Unsubscribe / resubscribe from events when it makes sense to avoid memory leaks
- GENERALLY Unless multiple subscription is required, try to avoid C# events in Xamarin.
BAD
this.Closed += (sender, args) {
if(args.IsTrue)
{
PerformActions(args);
}
}
GOOD
public override void ViewDidAppear()
{
this.Closed += FrameClosed;
}
public override void ViewDidDisappear()
{
this.Closed -= FrameClosed;
}
In code, acronyms should be treated as words. For example:
BAD:
XMLHTTPRequest
String URL
findPostByID
GOOD:
XmlHttpRequest
String url
findPostById
Access level modifiers should be explicitly defined for classes, methods and member variables. Avoid using default visibility.
Prefer single declaration per line.
BAD:
string username, twitterHandle;
GOOD:
private string _username;
private string _twitterHandle;
Use implicit typing for local variables when the type of the variable is obvious from the right side of the assignment, or when the compiler would not be able to correctly determine the type.
GOOD:
// When the type of a variable is clear from the context, use var
// in the declaration.
var var1 = "This is clearly a string.";
var var2 = 27;
var var3 = Convert.ToInt32(Console.ReadLine());
Explicitly type the variable when the compiler would not be able to correctly determine the type, or explicitly typing would add pertinent information.
GOOD:
// When the type of a variable is not clear from the context, use an
// explicit type.
int var4 = ExampleClass.ResultSoFar();
Do not rely on the variable name to specify the type of the variable. It might not be correct.
BAD:
// Naming the following variable inputInt is misleading.
// It is a string.
var inputInt = Console.ReadLine();
Console.WriteLine(inputInt);
Avoid the use of var in place of dynamic.
Use implicit typing to determine the type of the loop variable in for and foreach loops.
GOOD:
for Loop
var syllable = "ha";
var laugh = "";
for (var i = 0; i < 10; i++)
{
laugh += syllable;
Console.WriteLine(laugh);
}
foreach Loop
foreach (var ch in laugh)
{
if (ch == 'h')
Console.Write("H");
else
Console.Write(ch);
}
Console.WriteLine();
Exactly one class per source file, although inner classes are encouraged where scoping appropriate.
Interfaces that have one explicit implementation (service classes for example) may be declared in the same file as the classes that implement them.
All interfaces should be prefaced with the letter I.
BAD:
RadialSlider
GOOD:
IRadialSlider
Indentation should be done using spaces — never tabs.
Indentation for blocks uses 4 spaces for optimal readability:
BAD:
for (int i = 0; i < 10; i++)
{
Debug.Log("index=" + i);
}
GOOD:
for (int i = 0; i < 10; i++)
{
Debug.Log("index=" + i);
}
Indentation for line wraps should use 4 spaces (not the default 8):
BAD:
CoolUiWidget widget =
someIncrediblyLongExpression(that, reallyWouldNotFit, on, aSingle, line);
GOOD:
CoolUiWidget widget =
someIncrediblyLongExpression(that, reallyWouldNotFit, on, aSingle, line);
There should be exactly one blank line between methods to aid in visual clarity and organization. Whitespace within methods should separate functionality, but having too many sections in a method often means you should refactor into several methods.
All braces get their own line as it is a C# convention:
BAD:
class MyClass {
void DoSomething() {
if (someTest) {
// ...
} else {
// ...
}
}
}
GOOD:
class MyClass
{
void DoSomething()
{
if (someTest)
{
// ...
}
else
{
// ...
}
}
}
The one exception to braces on their own line is for anonymous functions, where the brace should go on the same line.
BAD:
Filter( (x)
{
if(x.IsComplicated)
{
return x > 5 + x.FirstSum;
}
return x < 4 + x.SecondSum;
});
GOOD:
Filter( (x) {
if(x.IsComplicated)
{
return x > 5 + x.FirstSum;
}
return x < 4 + x.SecondSum;
});
Conditional statements are always required to be enclosed with braces, irrespective of the number of lines required.
BAD:
if (someTest)
doSomething();
if (someTest) doSomethingElse();
GOOD:
if (someTest)
{
doSomething();
}
if (someTest) { doSomethingElse(); }
Switch-statements come with default
case by default (heh). When your code is written correctly, it should never reach this part.
Never include the default
case.
BAD:
switch (variable)
{
case 1:
break;
case 2:
break;
default:
break;
}
GOOD:
switch (variable)
{
case 1:
break;
case 2:
break;
}
Use US English spelling.
BAD:
string colour = "red";
GOOD:
string color = "red";
This style guide was forked from the collaborative effort from the most stylish raywenderlich.com team members:
And some guidelines pulled from Microsoft's C# Coding Conventions and .NET Design Guidelines