C# 风格指南¶
对于每个项目来说,拥有定义良好且一致的编码约定都是很重要的,而godot也不例外。
此页面包含一个编码样式指南,随后是Godot本身的开发人员和贡献者。因此,它主要针对那些希望为项目做出贡献的人,但是由于本文中提到的公约和准则是语言用户最广泛采用的,我们鼓励您这样做,特别是如果您还没有这样的指南。
注解
本文绝不是关于如何遵循标准编码约定或最佳实践的详尽指南。如果您不确定此处未涉及的方面,请参阅更全面的文档,例如 C# Coding Conventions 或 Framework Design Guidelines .
语言规范¶
Godot目前使用 C# version 7.0 在它的引擎和示例源代码中。因此,在我们转到新版本之前,必须注意避免混合仅在C# 7.1或更高版本中可用的语言功能。
有关不同版本的C# 功能的详细信息,请参阅 What's New in C# .
格式设置约定¶
使用换行符( LF )要换行的字符,而不是CRLF或CR。
使用 UTF-8 不带的编码 byte order mark .
使用 4个空格 而不是用于缩进的制表符(称为“软制表符”)。
如果一行超过100个字符,请考虑将它分成若干行。
换行符和空行¶
对于一般缩进规则,请遵循 the "Allman Style" 建议将与控制语句关联的大括号放在下一行,缩进到同一级别:
// 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
关键词。在单行访问器块之前和之内。
在单行访问器块中的访问器之间。
在一个不在行尾的逗号之后。
在a中的分号之后
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}; // 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.
}
}
命名约定¶
使用 PascalCase 对于所有命名空间、类型名和成员级标识符(即方法、属性、常量、事件),除了专用字段:
namespace ExampleProject
{
public class PlayerCharacter
{
public const float DefaultSpeed = 10f;
public float CurrentSpeed { get; set; }
protected int HitPoints;
private void CalculateWeaponDamage()
{
}
}
}
使用 骆驼壳 对于所有其他标识符(即局部变量、方法参数),并使用下划线 (_
)作为私有字段的前缀(但不用于方法或属性,如上所述):
private Vector3 _aimingAt; // Use a `_` prefix for private fields.
private void Attack(float attackStrength)
{
Enemy targetFound = FindTarget(_aimingAt);
targetFound?.Hit(attackStrength);
}
首字母缩略词有一个例外,它由两个字母组成,比如 UI
它应该用大写字母写,而pascalcase应该用小写字母写。
注意 id
是 not 一个缩写词,因此它应该被视为一个正常的标识符:
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;
其他注意事项¶
使用显式访问修饰符。
使用属性而不是非私有字段。
按以下顺序使用修饰符:
public
/protected
/`` private`/`` internal``/`` virtual``/`` override``/`` abstract``/`` new``/`` static``/`` readonly``。避免使用完全限定名或
this.
不需要时为成员添加前缀。移除未使用的
using
语句和不必要的括号。考虑省略类型的默认初始值。
考虑使用空条件运算符或类型初始值设定项使代码更紧凑。
如果值可能是其他类型,请使用安全强制转换,否则使用直接强制转换。