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. -
42
andtrue
) should use named parameters:SomeFunction(answer: 42)
- Callbacks passed to native code need to be static methods marked with the
[MonoPInvokeCallback]
attribute.GCHandle
should be used for dynamic object storage and lookup. - Disposable objects should throw
ObjectDisposedException
when methods are called on them, where appropriate. - Use interpolation strings,
string.Format
, orLog*Format
rather 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.x
support in the SpatialOS GDK for Unity (mandated by use of the Unity ECS). This equates toC# 7
so newer language features are supported. - Implement logic in a
ComponentSystem
instead of aMonoBehaviour
wherever possible. - Make sure you remove all
Debug.Log
statements before opening a PR. - Avoid running
foreach
over 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
ifdef
s:- 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.2
or 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
== null
when testingGameObject
s andMonoBehaviour
s even though they overload theoperator!
. - Avoid using custom threads. They complicate things and can easily cause crashes.