Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
C# 風格指南
明確且一致的程式編寫慣例對每個專案都很重要,Godot 也不例外。
本頁包含了程式風格指南,Godot 的開發者與貢獻者都會遵循。因此,這份指南主要是給想要貢獻 Godot 專案的人。但因為本文所列的慣例與指引也是該語言最廣泛採用的寫法,我們也鼓勵你參考採用,尤其如果你還沒有一份自己的風格指南時。
備註
本文章並非一份涵蓋所有標準程式設計慣例或最佳實踐的完整指南。如果你對本文未涵蓋的部分感到疑慮,請參考更完整的說明文件,例如 C# 編碼慣例 或 Framework 設計指引 。
語言規範
Godot 目前在引擎與範例程式碼中使用 C# 12.0 版,這是因為 .NET 8.0(目前的基本需求)所支援的版本。因此,在升級到新版本前,應避免混用僅在 C# 13.0 或更新版本才有的語言功能。
更多關於不同 C# 版本功能的資訊,請參考 C# 新功能 。
格式
通用指引
換行時請使用 LF 字元,不要用 CRLF 或 CR。
除了 csproj 檔案外,每個檔案結尾請用一個 LF 換行字元。
請使用無 BOM 的 UTF-8 編碼。
縮排請使用 4 個空白字元,不要用 Tab 字元(這稱為「軟 Tab」)。
當一行超過 100 個字元時,建議拆成多行。
換行與空白行
一般縮排建議遵循 Allman 風格 ,也就是將控制敘述的大括號放在下一行,並與該行縮排對齊:
// Use this style:
if (x > 0)
{
DoSomething();
}
// NOT this:
if (x > 0) {
DoSomething();
}
但你可以在以下情況省略大括號內的換行:
用於簡單的屬性存取子。
用於簡單的物件、陣列或集合初始值。
用於抽象自動屬性、索引子或事件宣告。
// 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};
}
}
}
應插入空行的情況:
在
using陳述式列表之後。在方法、屬性與內部型別宣告之間。
在每個檔案的結尾。
欄位與常數的宣告可以根據相關性分組。這種情況下,建議在不同群組間插入空行以方便閱讀。
應避免插入空行的情況:
在
{左大括號之後。在
}右大括號之前。在註解區塊或單行註解之後。
在另一個空行旁邊時。
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; // Related constants or fields can be
private Vector3 _y; // 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()
{
}
}
空白字元使用
應插入空白字元的情況:
在二元與三元運算子兩側。
在左括號與
if、for、foreach、catch、while、lock或using關鍵字之間。在單行存取子區塊之前與區塊內。
在單行存取子區塊的存取子之間。
在不是行尾的逗號後方。
在
for陳述式中的分號之後。在單行
case陳述式的冒號之後。在型別宣告中的冒號兩側。
在 Lambda 箭頭的兩側。
在單行註解符號(
//)之後,若用於行尾則也要在前面加空白。於單行初始化式中,在左大括號之後與右大括號之前插入空白字元。
以下情形不使用空白字元:
在型別轉換的括號後方。
以下範例根據上述慣例展示了正確的空白字元用法:
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 };
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.
}
}
命名慣例
所有命名空間、型別名稱以及成員層級識別子(如方法、屬性、常數、事件)都使用 PascalCase,Private 欄位除外:
namespace ExampleProject
{
public class PlayerCharacter
{
public const float DefaultSpeed = 10f;
public float CurrentSpeed { get; set; }
protected int HitPoints;
private void CalculateWeaponDamage()
{
}
}
}
其他所有識別子(如區域變數、方法參數)請用 camelCase。Private 欄位請在前面加底線(_)(但方法與屬性不加,如上所述):
private Vector3 _aimingAt; // Use an `_` prefix for private fields.
private void Attack(float attackStrength)
{
Enemy targetFound = FindTarget(_aimingAt);
targetFound?.Hit(attackStrength);
}
有個例外,像 UI 這種只有兩個字母的縮寫,在需要 PascalCase 的場合請用全大寫,其餘情況請用小寫。
請注意,id 不是 縮寫,應當作一般識別子處理:
public string Id { get; }
public UIManager UI
{
get { return uiManager; }
}
一般不建議用型別名稱作為識別子的前綴,例如 string strText 或 float fPower。不過介面是例外,介面名稱前面 應該 加上大寫的 I,如 IInventoryHolder 或 IDamageable。
最後,請盡量選擇具描述性的名稱,不要為了簡短而犧牲可讀性。
舉例來說,如果你要寫尋找鄰近敵人並用武器攻擊的程式,建議這樣命名:
FindNearbyEnemy()?.Damage(weaponDamage);
而不是:
FindNode()?.Change(wpnDmg);
成員變數
如果某個變數只會在一個方法內使用,不要把它宣告成成員變數。這會讓程式碼難以追蹤。請直接在方法內宣告為區域變數。
區域變數
區域變數請盡量在首次使用的附近宣告。這樣能讓程式碼更易閱讀,也不用頻繁捲動去尋找變數的宣告位置。
隱含型別區域變數
建議可以用隱含型別(var)宣告區域變數,但**僅限於型別能從指派右側明確判斷時**:
// 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 the `real_t` alias in Godot, which can either be double or float
// depending on the build configuration.
var value = 1.5;
其他注意事項
請使用明確的存取修飾詞。
請用屬性取代非 private 欄位。
修飾詞的順序應為:
public/protected/private/internal/virtual/override/abstract/new/static/readonly。不必要時請避免對成員用完整限定名稱或
this.前綴。請移除未使用的
using陳述式與不必要的括號。可省略型別的預設初值。
建議使用 null 條件運算子或型別初始化式讓程式碼更精簡。
當數值有可能是不同型別時請用安全轉型,否則可用直接轉型。