mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-04 14:11:02 +03:00
Merge pull request #1394 from mysticfall/master
#1296: Create official Godot C# style guide
This commit is contained in:
committed by
mhilbrunner
parent
3961c60f86
commit
7e9bd53ce6
305
getting_started/scripting/c_sharp/c_sharp_style_guide.rst
Normal file
305
getting_started/scripting/c_sharp/c_sharp_style_guide.rst
Normal file
@@ -0,0 +1,305 @@
|
||||
.. _doc_c_sharp_styleguide:
|
||||
|
||||
Style Guide
|
||||
===========
|
||||
|
||||
Having well-defined and consistent coding conventions is important for every project, and Godot
|
||||
is no exception to this rule.
|
||||
|
||||
This page contains a coding style guide which is followed by developers and contributors of Godot
|
||||
itself. As such, it is mainly intended for those who want to contribute to the project, but since
|
||||
the conventions and guidelines mentioned in this article are those most widely adopted by the users
|
||||
of the language, we encourage you to do the same, especially if you do not have such a guide yet.
|
||||
|
||||
.. note:: This article is by no means an exhaustive guide on how to follow the standard coding
|
||||
conventions or best practices. If you feel unsure of an aspect which is not covered here,
|
||||
please refer to more comprehensive documentation, such as
|
||||
`C# Coding Conventions <https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions>`_ or
|
||||
`Framework Design Guidelines <https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines>`_.
|
||||
|
||||
Language Specification
|
||||
----------------------
|
||||
|
||||
Currently, Godot uses C# version 6.0 in its engine and example source code. So, before we move to
|
||||
a newer version, care must be taken to avoid mixing language features only available in C# 7.0 or
|
||||
later, such as pattern matching or expression-bodied members inside get/set accessors.
|
||||
|
||||
For detailed information of C# features in different versions, please see
|
||||
`What's New in C# <https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/>`_.
|
||||
|
||||
Formatting Conventions
|
||||
----------------------
|
||||
|
||||
* If you create a new file, make sure that it uses linefeed (*LF*) characters to break lines, not *CRLF* or *CR*.
|
||||
* Use UTF-8 encoding without a byte order mark (BOM <https://en.wikipedia.org/wiki/Byte_order_mark>).
|
||||
* Use 4 spaces instead of tabs for indentation (which is referred to as 'soft tabs').
|
||||
|
||||
Line Breaks and Blank Lines
|
||||
---------------------------
|
||||
|
||||
For a general indentation rule, follow `The 'Allman Style' <https://en.wikipedia.org/wiki/Indentation_style#Allman_style>`_
|
||||
which recommends placing the brace associated with a control statement on the next line, indented to
|
||||
the same level:
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
// Use this style:
|
||||
if (x > 0)
|
||||
{
|
||||
DoSomething();
|
||||
}
|
||||
|
||||
// NOT this:
|
||||
if (x > 0) {
|
||||
DoSomething();
|
||||
}
|
||||
|
||||
However, you may choose to omit line breaks inside brackets,
|
||||
|
||||
* For simple property accessors.
|
||||
* For simple object, array, or collection initializers.
|
||||
* For abstract auto property, indexer, or event declarations.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
// You may put the brackets in a single line in following cases:
|
||||
public interface MyInterface
|
||||
{
|
||||
int MyProperty { get; set; }
|
||||
}
|
||||
|
||||
public class MyClass : ParentClass
|
||||
{
|
||||
public int Value
|
||||
{
|
||||
get { return 0; }
|
||||
set
|
||||
{
|
||||
ArrayValue = new [] {value};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Insert a blank line,
|
||||
|
||||
* After *using* statement list.
|
||||
* Between method, properties, and inner type declarations.
|
||||
|
||||
Field and constant declarations can be grouped together according to relevance. In that case, consider
|
||||
inserting a blank line between the groups for easier reading.
|
||||
|
||||
Avoid inserting a blank line,
|
||||
|
||||
* After an opening bracket ('{').
|
||||
* Before a closing bracket ('}').
|
||||
* After a comment block, or a single line comment.
|
||||
* Adjacent to another blank line.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
using System;
|
||||
using Godot;
|
||||
// Blank line after using list.
|
||||
public class MyClass
|
||||
{ // No blank line after '{'.
|
||||
public enum MyEnum
|
||||
{
|
||||
Value,
|
||||
AnotherValue // No blank line before '}'.
|
||||
}
|
||||
// Blank line around inner types.
|
||||
public const int SomeConstant = 1;
|
||||
public const int AnotherConstant = 2;
|
||||
|
||||
private Vector3 _x;
|
||||
private Vector3 _y; // Related constants or fields can be
|
||||
// grouped together.
|
||||
private float _width;
|
||||
private float _height;
|
||||
|
||||
public int MyProperty { get; set; }
|
||||
// Blank line around properties.
|
||||
public void MyMethod()
|
||||
{
|
||||
// Some comment.
|
||||
AnotherMethod(); // No blank line after a comment.
|
||||
}
|
||||
// Blank line around methods.
|
||||
public void AnotherMethod()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Consider breaking a line when it's longer than 100 characters. And it's also a good practice to
|
||||
insert a line feed (LF) character at the end of a file because some utilities have trouble
|
||||
recognizing the last line without it (i.e. Linux's *cat* command).
|
||||
|
||||
Using Spaces
|
||||
------------
|
||||
|
||||
Insert a space,
|
||||
|
||||
* Around a binary and tertiary operator.
|
||||
* Between an opening parenthesis and *if*, *for*, *foreach*, *catch*, *while*, *lock* or *using* keywords.
|
||||
* Before and within a single line accessor block.
|
||||
* Between accessors in a single line accessor block.
|
||||
* After a comma.
|
||||
* After a semi-colon in a *for* statement.
|
||||
* After a colon in a single line *case* statement.
|
||||
* Around a colon in a type declaration.
|
||||
* Around a lambda arrow.
|
||||
* After a single line comment symbol ('//'), and before it if used at the end of a line.
|
||||
|
||||
Do not use a space,
|
||||
|
||||
* After a type cast parentheses.
|
||||
* Within single line initializer braces.
|
||||
|
||||
The following example shows a proper use of spaces, according to some of the the above mentioned conventions:
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public class MyClass<A, B> : Parent<A, B>
|
||||
{
|
||||
public float MyProperty { get; set; }
|
||||
|
||||
public float AnotherProperty
|
||||
{
|
||||
get { return MyProperty; }
|
||||
}
|
||||
|
||||
public void MyMethod()
|
||||
{
|
||||
int[] values = {1, 2, 3, 4}; // No space within initializer brackets.
|
||||
int sum = 0;
|
||||
|
||||
// Single line comment.
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 3: return;
|
||||
default:
|
||||
sum += i > 2 ? 0 : 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i += (int)MyProperty; // No space after a type cast.
|
||||
}
|
||||
}
|
||||
|
||||
Naming Conventions
|
||||
------------------
|
||||
|
||||
Use *PascalCase* for all namespaces, type names and member level identifiers (i.e. methods, properties,
|
||||
constants, events), except for private fields:
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
namespace ExampleProject
|
||||
{
|
||||
public class PlayerCharacter
|
||||
{
|
||||
public const float DefaultSpeed = 10f;
|
||||
|
||||
public float CurrentSpeed { get; set; }
|
||||
|
||||
protected int HitPoints;
|
||||
|
||||
private void CalculateWeaponDamage()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Use *camelCase* for all other identifiers (i.e. local variables, method arguments), and use
|
||||
underscore('_') as a prefix for private fields (but not for methods or properties, as explained above):
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
private Vector3 _aimingAt; // Use '_' prefix for private fields.
|
||||
|
||||
private void Attack(float attackStrength)
|
||||
{
|
||||
Enemy targetFound = FindTarget(_aimingAt);
|
||||
|
||||
targetFound?.Hit(attackStrength);
|
||||
}
|
||||
|
||||
There's an exception with acronyms which consist of two letters like *'UI'* which should be written in
|
||||
upper case letters when used where Pascal case would be expected, and in lower case letters otherwise.
|
||||
|
||||
Note that *'id'* is **not** an acronym, so it should be treated as a normal identifier:
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public string Id { get; }
|
||||
|
||||
public UIManager UI
|
||||
{
|
||||
get { return uiManager; }
|
||||
}
|
||||
|
||||
It is generally discouraged to use a type name as a prefix of an identifier like *'string strText'*
|
||||
or *'float fPower'*, for example. However, there's an exception about interfaces, in which case they
|
||||
**should** be named using an upper case *'I'* as a prefix, like *'IInventoryHolder'* or *'IDamageable'*.
|
||||
|
||||
Lastly, consider choosing descriptive names and do not try to shorten them too much if it affects
|
||||
readability.
|
||||
|
||||
For instance, if you want to write a code to find a nearby enemy and hit with an weapon, prefer
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
FindNearbyEnemy()?.Damage(weaponDamage);
|
||||
|
||||
Rather than,
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
FindNode()?.Change(wpnDmg);
|
||||
|
||||
Implicitly Typed Local Variables
|
||||
--------------------------------
|
||||
|
||||
Consider using implicitly typing (*'var'*) for declaration of a local variable, but do so
|
||||
**only when the type is evident** from the right side of the assignment:
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
// You can use `var` for these cases:
|
||||
|
||||
var direction = new Vector2(1, 0);
|
||||
|
||||
var value = (int)speed;
|
||||
|
||||
var text = "Some value";
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
}
|
||||
|
||||
// But not for these:
|
||||
|
||||
var value = GetValue();
|
||||
|
||||
var velocity = direction * 1.5;
|
||||
|
||||
// It's generally a better idea to use explicit typing for numeric values, especially with
|
||||
// the existence of 'real_t' alias in Godot, which can either be double or float depending
|
||||
// on the build configuration.
|
||||
|
||||
var value = 1.5;
|
||||
|
||||
Other Considerations
|
||||
--------------------
|
||||
|
||||
* Use explicit access modifiers.
|
||||
* Use properties instead of non-private fields.
|
||||
* Use modifiers in this order: *'public/protected/private/internal virtual/override/abstract/new static readonly'*.
|
||||
* Avoid using fully qualified names or *'this.'* prefix for members when it's not necessary.
|
||||
* Remove unused *'using'* statements and unnecessary parentheses.
|
||||
* Consider omitting default initial value for a type.
|
||||
* Consider using null-conditional operators or type initializers to make the code more compact.
|
||||
* Use safe cast when there is a possibility of the value being a different type, and use direct cast otherwise.
|
||||
@@ -8,5 +8,6 @@ C#
|
||||
c_sharp_basics
|
||||
c_sharp_features
|
||||
c_sharp_differences
|
||||
c_sharp_style_guide
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user