C# Coding Standard

Table of Contents

Code formatting

Uncrustify code formatter

A C# compatible Uncrustify configuration is being investigated, however at the moment no such support is available.

Common rules

Curly Brackets

Curly brackets should always be on a new line

// good!
public MyGoodBar()
{
}
 
// bad
public MyGoodBar {
}
 
// Bad
public MyGoodBar {}

if statements

Curly brackets are always required, even for single-expression statements.

// Good
if(a < b)
{
    DoMainThing();
}
else if(a == b)
{
    DoSomething();
}
else
{
    DoOtherStuff();
}
 
// Bad
if (a < b)
    DoMainThing();
else if (a == b)
    DoSomething();
else
    DoOtherStuff();

Naming conventions

General naming rules

  • Use meaningful variable and type names never use inappropriate language like crap, shit
  • All names and comments should be in American English.
  • Avoid non common abbreviations.
  • Do not write “2” and “4” as replacement for "to" and "for".

Namespaces

Name of a namespace should be in PascalCase.

Always use namespaces to indicate a larger subsystem of the engine, to avoid cluttering the root CryEngine namespace.

Examples
  • CryEngine.EntitySystem
  • CryEngine.FlowSystem
  • CryEngine.Serialization

Class name

Name of a class should be in PascalCase, without any prefixes.

// Good
class MyClass
{
} 
 
// Bad
class CMyClass
{
}

Interface name

Name of an interface should be in PascalCase, prefixed with 'I'.

// Good
public interface IUpdateReceiver
{
} 
 
// Bad
public interface UpdateReceiver
{
} 

Enum names

Name of an enum should be descriptive and written in PascalCase. Enums and their values should not utilize prefixes.

// Good
enum SerializedObjectType
{
    Null,
    Primitive
}
 
// Bad
enum ESerializedObjectType
{
    Null,
    Primitive
}
 
// Bad
enum SerializedObjectType
{
    eNull,
    ePrimitive
}

Function name

Name of a function should be in PascalCase.

Always use Properties for simple get / set functionality.

Field name

Name of a field should always be prefixed with _ and a camelCase name. Wherever public fields are required, use Properties with automatically generated backing fields.

// Good
class Test
{
  int _someValue;
  bool _active;
} 
 
// Better
class Test
{
  int SomeValue { get; set; }
  bool Active { get; set; }
}
 
// Bad
class Test
{
  public int someValue;
  public int active;
} 

Property name

Name of a property should always use PascalCase without a prefix.

Whenever a property requires fields, opt for backing fields where possible.

// Good
class Test
{
  int SomeValue { get; set; }
  bool Active { get; set; }
}
 
// Bad
class Test
{
  int someValue { get; set; }
  bool active { get; set; }
}
 
// Bad
class Test
{
  int someValue;
  bool active;
 
  bool GetSomeValue() { return someValue; }
  bool IsActive() { return active; }
}

Static class members

Use class members instead of separate managers for finding and manipulating instances.

// Good (usage: var myEntity = Entity.Spawn<MyEntity>();
public partial class Entity
{
  public static T Spawn<T>() where T : Entity, new()
  {
    // return ...
  }
}
 
// Bad
public class EntityFramework
{
  public static T Spawn<T>() where T : Entity
  {
    // return ...
  }
} 

Comments

Every method and property that's either public or protected must have a summary. Summaries are in XML style and always positioned on the line before the object they describe.

// Good
/// <summary>
/// Clamps the specified value between 0 and 1.
/// </summary>
/// <returns>The value clamped between 0 and 1.</returns>
/// <param name="value">Value that needs to be clamped.</param>
public static float Clamp01(float value)
{
  // return ...
}
 
// Bad
public CheckBoxCtrl Ctrl; ///< The UIComponent controlling this element.

Files

File naming

The source file should always have the same name as the main type that resides inside it. Split out separate classes into multiple files.

Class layout

  • Define members in the following order:
    1. Fields
    2. Properties
    3. Methods
    4. Static Methods

Code quality

Unsafe

Our libraries can never contain unsafe code.

Loops

Use the correct loop for the proper context, for example simply iterating data in a container always use foreach.