Style Guide

  • Follow C# conventions for stuff not otherwise mentioned
  • Use PascalCase for the following (Things that can't change)
    • Readonly/const fields
    • Readonly properties
    • Enum members
    • Methods
    • Types
  • Use camelCase for the following (Things that can change)
    • Fields
    • Properties
    • Local variables
    • Method parameters
  • Function/Class/Struct/Delegate/Enum Declarations should be separated by at least one empty line
    โ€‹โ€‹โ€‹โ€‹// Yes
    โ€‹โ€‹โ€‹โ€‹void OwO() {
    โ€‹โ€‹โ€‹โ€‹    //...
    โ€‹โ€‹โ€‹โ€‹}
    โ€‹โ€‹โ€‹โ€‹
    โ€‹โ€‹โ€‹โ€‹void UwU() {
    โ€‹โ€‹โ€‹โ€‹    //...
    โ€‹โ€‹โ€‹โ€‹}
    โ€‹โ€‹โ€‹โ€‹
    โ€‹โ€‹โ€‹โ€‹// No
    โ€‹โ€‹โ€‹โ€‹void OwO() {
    โ€‹โ€‹โ€‹โ€‹    //...
    โ€‹โ€‹โ€‹โ€‹}
    โ€‹โ€‹โ€‹โ€‹void UwU() {
    โ€‹โ€‹โ€‹โ€‹    //...
    โ€‹โ€‹โ€‹โ€‹}
    
  • Acronyms should be treated like words
    • Gui, not GUI
  • Package names shouldn't repeat the parent(s)
    โ€‹โ€‹โ€‹โ€‹// Yes
    โ€‹โ€‹โ€‹โ€‹namespace Voxel.World.Settings;
    โ€‹โ€‹โ€‹โ€‹// No
    โ€‹โ€‹โ€‹โ€‹namespace Voxel.World.WorldSettings;
    
  • Backing fields of properties should be named the same as the property they're backing, but prefixed with an _
  • Generics should be prefixed with T, otherwise types (Classes/Interfaces/etc) should not be prefixed
    • Tkey - Good
    • IBlockView - Bad
  • Braces should be on the same line, OTB style
    • Space should be in control statements like if, while, etc
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹if (someCond) {
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    // Do something
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹}
      
    • Control statements should always exclude braces only when all branches run one line of code
      • That line of code should be on a new line
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹// Yes
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹if (someCond)
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoSomething();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹else
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoSomethingElse();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹// Yes
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹if (anotherCond) {
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoSomething();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹} else {
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoSomethingElse();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoAThirdThing();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹}
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹// No
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹if (aThirdCond)
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoSomething();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹else {
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoSomethingElse();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    DoAThirdThing();
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹}
      
      • else switch, else while, etc are disallowed
  • Spaces should surround math operators, except the inside of parenthesis
    • 1 + 5 instead of 1+5
    • (1 + 5) * 2 instead of ( 1 + 5 ) * 2
  • If a property only has a getter, prefer int Value => v;
  • Prefer => notation in methods/properties that immediately return.
    • Prefer newline for methods
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹int DoSomething(int x)
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    => x * 15;
      
    • Prefer no newline for properties
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹int something => DoSomething(6) - 12;
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹float somethingElse {
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    get => x;
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹    set => x = value;
      โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹โ€‹}
      
  • 4 spaces
  • Prefer var when possible, as well as new(/*...*/)
    • var thing = new Thing();
    • Primitive types are an exception
      • int thing = 15 over var thing = 15
  • Prefer x as Thing over of (Thing) x whenever possible
    • var thing = x as Thing
  • Always mark nullable variables as nullable
    • Thing? thing
  • this. should be used only when necessary
  • Ordering of members in types
    • Const -> readonly -> mutable
    • Static -> non-static
    • Public -> private -> protected -> internal
    • Delegates -> fields/properties -> constructors -> methods -> sub-types
  • Unsafe functions and blocks should have a comment explaining safety, like in Rust.
    โ€‹โ€‹โ€‹โ€‹// SAFETY: We know GetCString returns a valid pointer to a C String (or nullptr).
    โ€‹โ€‹โ€‹โ€‹unsafe {
    โ€‹โ€‹โ€‹โ€‹    byte *ptr = GetCString();
    โ€‹โ€‹โ€‹โ€‹    var str = Marshal.PtrToStringUTF8((nint)ptr);
    โ€‹โ€‹โ€‹โ€‹}
    
  • TODOs should have a colon, not a dash
    โ€‹โ€‹โ€‹โ€‹// TODO: Do this
    โ€‹โ€‹โ€‹โ€‹// TODO - Not this