c_sharp_style_guide.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. .. _doc_c_sharp_styleguide:
  2. C# 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 of and contributors to 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. Godot currently uses **C# version 10.0** in its engine and example source code,
  18. as this is the version supported by .NET 6.0 (the current baseline requirement).
  19. So, before we move to a newer version, care must be taken to avoid mixing
  20. language features only available in C# 11.0 or later.
  21. For detailed information on C# features in different versions, please see
  22. `What's New in C# <https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/>`_.
  23. Formatting
  24. ----------
  25. General guidelines
  26. ~~~~~~~~~~~~~~~~~~
  27. * Use line feed (**LF**) characters to break lines, not CRLF or CR.
  28. * Use one line feed character at the end of each file, except for `csproj` files.
  29. * Use **UTF-8** encoding without a `byte order mark <https://en.wikipedia.org/wiki/Byte_order_mark>`_.
  30. * Use **4 spaces** instead of tabs for indentation (which is referred to as "soft tabs").
  31. * Consider breaking a line into several if it's longer than 100 characters.
  32. Line breaks and blank lines
  33. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  34. For a general indentation rule, follow `the "Allman Style" <https://en.wikipedia.org/wiki/Indentation_style#Allman_style>`_
  35. which recommends placing the brace associated with a control statement on the next line, indented to
  36. the same level:
  37. .. code-block:: csharp
  38. // Use this style:
  39. if (x > 0)
  40. {
  41. DoSomething();
  42. }
  43. // NOT this:
  44. if (x > 0) {
  45. DoSomething();
  46. }
  47. However, you may choose to omit line breaks inside brackets:
  48. * For simple property accessors.
  49. * For simple object, array, or collection initializers.
  50. * For abstract auto property, indexer, or event declarations.
  51. .. code-block:: csharp
  52. // You may put the brackets in a single line in following cases:
  53. public interface MyInterface
  54. {
  55. int MyProperty { get; set; }
  56. }
  57. public class MyClass : ParentClass
  58. {
  59. public int Value
  60. {
  61. get { return 0; }
  62. set
  63. {
  64. ArrayValue = new [] {value};
  65. }
  66. }
  67. }
  68. Insert a blank line:
  69. * After a list of ``using`` statements.
  70. * Between method, properties, and inner type declarations.
  71. * At the end of each file.
  72. Field and constant declarations can be grouped together according to relevance. In that case, consider
  73. inserting a blank line between the groups for easier reading.
  74. Avoid inserting a blank line:
  75. * After ``{``, the opening brace.
  76. * Before ``}``, the closing brace.
  77. * After a comment block or a single-line comment.
  78. * Adjacent to another blank line.
  79. .. code-block:: csharp
  80. using System;
  81. using Godot;
  82. // Blank line after `using` list.
  83. public class MyClass
  84. { // No blank line after `{`.
  85. public enum MyEnum
  86. {
  87. Value,
  88. AnotherValue // No blank line before `}`.
  89. }
  90. // Blank line around inner types.
  91. public const int SomeConstant = 1;
  92. public const int AnotherConstant = 2;
  93. private Vector3 _x; // Related constants or fields can be
  94. private Vector3 _y; // grouped together.
  95. private float _width;
  96. private float _height;
  97. public int MyProperty { get; set; }
  98. // Blank line around properties.
  99. public void MyMethod()
  100. {
  101. // Some comment.
  102. AnotherMethod(); // No blank line after a comment.
  103. }
  104. // Blank line around methods.
  105. public void AnotherMethod()
  106. {
  107. }
  108. }
  109. Using spaces
  110. ~~~~~~~~~~~~
  111. Insert a space:
  112. * Around a binary and ternary operator.
  113. * Between an opening parenthesis and ``if``, ``for``, ``foreach``, ``catch``, ``while``, ``lock`` or ``using`` keywords.
  114. * Before and within a single line accessor block.
  115. * Between accessors in a single line accessor block.
  116. * After a comma which is not at the end of a line.
  117. * After a semicolon in a ``for`` statement.
  118. * After a colon in a single line ``case`` statement.
  119. * Around a colon in a type declaration.
  120. * Around a lambda arrow.
  121. * After a single-line comment symbol (``//``), and before it if used at the end of a line.
  122. * After the opening brace, and before the closing brace in a single line initializer.
  123. Do not use a space:
  124. * After type cast parentheses.
  125. The following example shows a proper use of spaces, according to some of the above mentioned conventions:
  126. .. code-block:: csharp
  127. public class MyClass<A, B> : Parent<A, B>
  128. {
  129. public float MyProperty { get; set; }
  130. public float AnotherProperty
  131. {
  132. get { return MyProperty; }
  133. }
  134. public void MyMethod()
  135. {
  136. int[] values = { 1, 2, 3, 4 };
  137. int sum = 0;
  138. // Single line comment.
  139. for (int i = 0; i < values.Length; i++)
  140. {
  141. switch (i)
  142. {
  143. case 3: return;
  144. default:
  145. sum += i > 2 ? 0 : 1;
  146. break;
  147. }
  148. }
  149. i += (int)MyProperty; // No space after a type cast.
  150. }
  151. }
  152. Naming conventions
  153. ------------------
  154. Use **PascalCase** for all namespaces, type names and member level identifiers (i.e. methods, properties,
  155. constants, events), except for private fields:
  156. .. code-block:: csharp
  157. namespace ExampleProject
  158. {
  159. public class PlayerCharacter
  160. {
  161. public const float DefaultSpeed = 10f;
  162. public float CurrentSpeed { get; set; }
  163. protected int HitPoints;
  164. private void CalculateWeaponDamage()
  165. {
  166. }
  167. }
  168. }
  169. Use **camelCase** for all other identifiers (i.e. local variables, method arguments), and use
  170. an underscore (``_``) as a prefix for private fields (but not for methods or properties, as explained above):
  171. .. code-block:: csharp
  172. private Vector3 _aimingAt; // Use a `_` prefix for private fields.
  173. private void Attack(float attackStrength)
  174. {
  175. Enemy targetFound = FindTarget(_aimingAt);
  176. targetFound?.Hit(attackStrength);
  177. }
  178. There's an exception with acronyms which consist of two letters, like ``UI``, which should be written in
  179. uppercase letters where PascalCase would be expected, and in lowercase letters otherwise.
  180. Note that ``id`` is **not** an acronym, so it should be treated as a normal identifier:
  181. .. code-block:: csharp
  182. public string Id { get; }
  183. public UIManager UI
  184. {
  185. get { return uiManager; }
  186. }
  187. It is generally discouraged to use a type name as a prefix of an identifier, like ``string strText``
  188. or ``float fPower``, for example. An exception is made, however, for interfaces, which
  189. **should**, in fact, have an uppercase letter ``I`` prefixed to their names, like ``IInventoryHolder`` or ``IDamageable``.
  190. Lastly, consider choosing descriptive names and do not try to shorten them too much if it affects
  191. readability.
  192. For instance, if you want to write code to find a nearby enemy and hit it with a weapon, prefer:
  193. .. code-block:: csharp
  194. FindNearbyEnemy()?.Damage(weaponDamage);
  195. Rather than:
  196. .. code-block:: csharp
  197. FindNode()?.Change(wpnDmg);
  198. Member variables
  199. ----------------
  200. Don't declare member variables if they are only used locally in a method, as it
  201. makes the code more difficult to follow. Instead, declare them as local
  202. variables in the method's body.
  203. Local variables
  204. ---------------
  205. Declare local variables as close as possible to their first use. This makes it
  206. easier to follow the code, without having to scroll too much to find where the
  207. variable was declared.
  208. Implicitly typed local variables
  209. --------------------------------
  210. Consider using implicitly typing (``var``) for declaration of a local variable, but do so
  211. **only when the type is evident** from the right side of the assignment:
  212. .. code-block:: csharp
  213. // You can use `var` for these cases:
  214. var direction = new Vector2(1, 0);
  215. var value = (int)speed;
  216. var text = "Some value";
  217. for (var i = 0; i < 10; i++)
  218. {
  219. }
  220. // But not for these:
  221. var value = GetValue();
  222. var velocity = direction * 1.5;
  223. // It's generally a better idea to use explicit typing for numeric values, especially with
  224. // the existence of the `real_t` alias in Godot, which can either be double or float
  225. // depending on the build configuration.
  226. var value = 1.5;
  227. Other considerations
  228. --------------------
  229. * Use explicit access modifiers.
  230. * Use properties instead of non-private fields.
  231. * Use modifiers in this order:
  232. ``public``/``protected``/``private``/``internal``/``virtual``/``override``/``abstract``/``new``/``static``/``readonly``.
  233. * Avoid using fully-qualified names or ``this.`` prefix for members when it's not necessary.
  234. * Remove unused ``using`` statements and unnecessary parentheses.
  235. * Consider omitting the default initial value for a type.
  236. * Consider using null-conditional operators or type initializers to make the code more compact.
  237. * Use safe cast when there is a possibility of the value being a different type, and use direct cast otherwise.