c_sharp_style_guide.rst 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. .. _doc_c_sharp_styleguide:
  2. Style Guide
  3. ===========
  4. Having well-defined and consistent coding conventions is important for every project, and Godot
  5. is no exception to this rule.
  6. This page contains a coding style guide which is followed by developers and contributors of Godot
  7. itself. As such, it is mainly intended for those who want to contribute to the project, but since
  8. the conventions and guidelines mentioned in this article are those most widely adopted by the users
  9. of the language, we encourage you to do the same, especially if you do not have such a guide yet.
  10. .. note:: This article is by no means an exhaustive guide on how to follow the standard coding
  11. conventions or best practices. If you feel unsure of an aspect which is not covered here,
  12. please refer to more comprehensive documentation, such as
  13. `C# Coding Conventions <https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions>`_ or
  14. `Framework Design Guidelines <https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines>`_.
  15. Language Specification
  16. ----------------------
  17. Currently, Godot uses C# version 6.0 in its engine and example source code. So, before we move to
  18. a newer version, care must be taken to avoid mixing language features only available in C# 7.0 or
  19. later, such as pattern matching or expression-bodied members inside get/set accessors.
  20. For detailed information of C# features in different versions, please see
  21. `What's New in C# <https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/>`_.
  22. Formatting Conventions
  23. ----------------------
  24. * If you create a new file, make sure that it uses linefeed (*LF*) characters to break lines, not *CRLF* or *CR*.
  25. * Use UTF-8 encoding without a byte order mark (BOM <https://en.wikipedia.org/wiki/Byte_order_mark>).
  26. * Use 4 spaces instead of tabs for indentation (which is referred to as 'soft tabs').
  27. Line Breaks and Blank Lines
  28. ---------------------------
  29. For a general indentation rule, follow `The 'Allman Style' <https://en.wikipedia.org/wiki/Indentation_style#Allman_style>`_
  30. which recommends placing the brace associated with a control statement on the next line, indented to
  31. the same level:
  32. .. code-block:: csharp
  33. // Use this style:
  34. if (x > 0)
  35. {
  36. DoSomething();
  37. }
  38. // NOT this:
  39. if (x > 0) {
  40. DoSomething();
  41. }
  42. However, you may choose to omit line breaks inside brackets,
  43. * For simple property accessors.
  44. * For simple object, array, or collection initializers.
  45. * For abstract auto property, indexer, or event declarations.
  46. .. code-block:: csharp
  47. // You may put the brackets in a single line in following cases:
  48. public interface MyInterface
  49. {
  50. int MyProperty { get; set; }
  51. }
  52. public class MyClass : ParentClass
  53. {
  54. public int Value
  55. {
  56. get { return 0; }
  57. set
  58. {
  59. ArrayValue = new [] {value};
  60. }
  61. }
  62. }
  63. Insert a blank line,
  64. * After *using* statement list.
  65. * Between method, properties, and inner type declarations.
  66. Field and constant declarations can be grouped together according to relevance. In that case, consider
  67. inserting a blank line between the groups for easier reading.
  68. Avoid inserting a blank line,
  69. * After an opening bracket ('{').
  70. * Before a closing bracket ('}').
  71. * After a comment block, or a single line comment.
  72. * Adjacent to another blank line.
  73. .. code-block:: csharp
  74. using System;
  75. using Godot;
  76. // Blank line after using list.
  77. public class MyClass
  78. { // No blank line after '{'.
  79. public enum MyEnum
  80. {
  81. Value,
  82. AnotherValue // No blank line before '}'.
  83. }
  84. // Blank line around inner types.
  85. public const int SomeConstant = 1;
  86. public const int AnotherConstant = 2;
  87. private Vector3 _x;
  88. private Vector3 _y; // Related constants or fields can be
  89. // grouped together.
  90. private float _width;
  91. private float _height;
  92. public int MyProperty { get; set; }
  93. // Blank line around properties.
  94. public void MyMethod()
  95. {
  96. // Some comment.
  97. AnotherMethod(); // No blank line after a comment.
  98. }
  99. // Blank line around methods.
  100. public void AnotherMethod()
  101. {
  102. }
  103. }
  104. Consider breaking a line when it's longer than 100 characters. And it's also a good practice to
  105. insert a line feed (LF) character at the end of a file because some utilities have trouble
  106. recognizing the last line without it (i.e. Linux's *cat* command).
  107. Using Spaces
  108. ------------
  109. Insert a space,
  110. * Around a binary and tertiary operator.
  111. * Between an opening parenthesis and *if*, *for*, *foreach*, *catch*, *while*, *lock* or *using* keywords.
  112. * Before and within a single line accessor block.
  113. * Between accessors in a single line accessor block.
  114. * After a comma.
  115. * After a semi-colon in a *for* statement.
  116. * After a colon in a single line *case* statement.
  117. * Around a colon in a type declaration.
  118. * Around a lambda arrow.
  119. * After a single line comment symbol ('//'), and before it if used at the end of a line.
  120. Do not use a space,
  121. * After a type cast parentheses.
  122. * Within single line initializer braces.
  123. The following example shows a proper use of spaces, according to some of the the above mentioned conventions:
  124. .. code-block:: csharp
  125. public class MyClass<A, B> : Parent<A, B>
  126. {
  127. public float MyProperty { get; set; }
  128. public float AnotherProperty
  129. {
  130. get { return MyProperty; }
  131. }
  132. public void MyMethod()
  133. {
  134. int[] values = {1, 2, 3, 4}; // No space within initializer brackets.
  135. int sum = 0;
  136. // Single line comment.
  137. for (int i = 0; i < values.Length; i++)
  138. {
  139. switch (i)
  140. {
  141. case 3: return;
  142. default:
  143. sum += i > 2 ? 0 : 1;
  144. break;
  145. }
  146. }
  147. i += (int)MyProperty; // No space after a type cast.
  148. }
  149. }
  150. Naming Conventions
  151. ------------------
  152. Use *PascalCase* for all namespaces, type names and member level identifiers (i.e. methods, properties,
  153. constants, events), except for private fields:
  154. .. code-block:: csharp
  155. namespace ExampleProject
  156. {
  157. public class PlayerCharacter
  158. {
  159. public const float DefaultSpeed = 10f;
  160. public float CurrentSpeed { get; set; }
  161. protected int HitPoints;
  162. private void CalculateWeaponDamage()
  163. {
  164. }
  165. }
  166. }
  167. Use *camelCase* for all other identifiers (i.e. local variables, method arguments), and use
  168. underscore('_') as a prefix for private fields (but not for methods or properties, as explained above):
  169. .. code-block:: csharp
  170. private Vector3 _aimingAt; // Use '_' prefix for private fields.
  171. private void Attack(float attackStrength)
  172. {
  173. Enemy targetFound = FindTarget(_aimingAt);
  174. targetFound?.Hit(attackStrength);
  175. }
  176. There's an exception with acronyms which consist of two letters like *'UI'* which should be written in
  177. upper case letters when used where Pascal case would be expected, and in lower case letters otherwise.
  178. Note that *'id'* is **not** an acronym, so it should be treated as a normal identifier:
  179. .. code-block:: csharp
  180. public string Id { get; }
  181. public UIManager UI
  182. {
  183. get { return uiManager; }
  184. }
  185. It is generally discouraged to use a type name as a prefix of an identifier like *'string strText'*
  186. or *'float fPower'*, for example. However, there's an exception about interfaces, in which case they
  187. **should** be named using an upper case *'I'* as a prefix, like *'IInventoryHolder'* or *'IDamageable'*.
  188. Lastly, consider choosing descriptive names and do not try to shorten them too much if it affects
  189. readability.
  190. For instance, if you want to write a code to find a nearby enemy and hit with an weapon, prefer
  191. .. code-block:: csharp
  192. FindNearbyEnemy()?.Damage(weaponDamage);
  193. Rather than,
  194. .. code-block:: csharp
  195. FindNode()?.Change(wpnDmg);
  196. Implicitly Typed Local Variables
  197. --------------------------------
  198. Consider using implicitly typing (*'var'*) for declaration of a local variable, but do so
  199. **only when the type is evident** from the right side of the assignment:
  200. .. code-block:: csharp
  201. // You can use `var` for these cases:
  202. var direction = new Vector2(1, 0);
  203. var value = (int)speed;
  204. var text = "Some value";
  205. for (var i = 0; i < 10; i++)
  206. {
  207. }
  208. // But not for these:
  209. var value = GetValue();
  210. var velocity = direction * 1.5;
  211. // It's generally a better idea to use explicit typing for numeric values, especially with
  212. // the existence of 'real_t' alias in Godot, which can either be double or float depending
  213. // on the build configuration.
  214. var value = 1.5;
  215. Other Considerations
  216. --------------------
  217. * Use explicit access modifiers.
  218. * Use properties instead of non-private fields.
  219. * Use modifiers in this order: *'public/protected/private/internal virtual/override/abstract/new static readonly'*.
  220. * Avoid using fully qualified names or *'this.'* prefix for members when it's not necessary.
  221. * Remove unused *'using'* statements and unnecessary parentheses.
  222. * Consider omitting default initial value for a type.
  223. * Consider using null-conditional operators or type initializers to make the code more compact.
  224. * Use safe cast when there is a possibility of the value being a different type, and use direct cast otherwise.