Contributions: We are not currently taking public contributions - see our contributions policy. However, we are accepting issues and we do want your feedback.
- SpatialOS GDK for Unity C# coding standards
Generally, we use Microsoft's C# Coding Conventions. See also the Framework Design Guidelines. Anything noted below overrides these conventions.
(Optional) Install ReSharper for Visual Studio.
Please format any code files that you've touched (normally Ctrl+Alt+F) before committing changes.
- Avoid interfaces with fewer than two implementations.
- Avoid extension methods. They can introduce magic and make implementation hard to find.
- Avoid Linq. It often introduces unnecessary allocation.
- Non-obvious constant-value arguments (e.g. -
42andtrue) should use named parameters:SomeFunction(answer: 42)
- Callbacks passed to native code need to be static methods marked with the
[MonoPInvokeCallback]attribute.GCHandleshould be used for dynamic object storage and lookup. - Disposable objects should throw
ObjectDisposedExceptionwhen methods are called on them, where appropriate. - Use interpolation strings,
string.Format, orLog*Formatrather than string concatenation.- ✅
var message = Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now."); - ✅
var message = String.Format("The current price is {0} per ounce.", pricePerOunce) - ❌
var message = "The current price is " + pricePerOunce + " per ounce."
- ✅
- Avoid lines longer than 120 characters.
- Use braces for any kind of conditional or loop statements.
- Add an empty line at the end of the file.
- Avoid any kind of redundant whitespace.
- Use spaces instead of tabs for indentation.
- PascalCase for class and method names.
- PascalCase for public variables and private const variables, camelCase for private variables.
- Acronyms have only their first letter capitalised in variable or method names. In comments, acronyms are fully-capitalised.
- ✅
EntityAcl GetEntityAcl(); - ❌
EntityACL GetEntityACL(); - ✅
var entityAcl = GetEntityAcl(); // Gets the Entity ACL. - ❌
var entityAcl = GetEntityAcl(); //Gets the Entity Acl.
- ✅
- Annotate deprecated functions with
[System.Obsolete(<string>)]where<string>is a short summary of the deprecation reason and either a guide on how to upgrade or a link to a guide on how to upgrade.
- Name test fixtures as
<class>Tests - Name test methods as
<method>_should_<action>_when_<conditions>
- We are using the
.NET 4.xsupport in the SpatialOS GDK for Unity (mandated by use of the Unity ECS). This equates toC# 7so newer language features are supported. - Implement logic in a
ComponentSysteminstead of aMonoBehaviourwherever possible. - Make sure you remove all
Debug.Logstatements before opening a PR. - Avoid running
foreachover anIEnumerable<T>because it allocates excessively. See this StackOverflow question for an explanation of whyIEnumerable<T>allocates. - Be aware of the possible allocations when using collections and avoid doing so where the volume would impact performance.
- When using structs as keys dictionaries, sets or in comparisons, ensure to implement a custom hash code function and the
IEquatable<>interface to avoid a performance drop. - Avoid using enums as dictionary keys. This leads to extra allocations due to boxing in the Mono runtime. The boxing can be avoided by implementing
EqualityComparer<MyEnum>for your enum as described here. - When writing Unity code that's not compatible with all supported versions of Unity, use
ifdefs:- Write all of them in a forward-compatible way.
- Write
if (!(UNITY_2018_0 | UNITY_2018_1))instead ofif (UNITY_2018_2)if you want to specify2018.2or newer. - Be careful with defines such as
UNITY_2018_1_OR_NEWER- they might not be available in all versions of Unity 2018.1.
- Use
== nullwhen testingGameObjects andMonoBehaviours even though they overload theoperator!. - Avoid using custom threads. They complicate things and can easily cause crashes.