<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[自用C#代码规范]]></title><description><![CDATA[<p dir="auto">在没有代码规范的情况下，一个多人合作的项目中很可能会出现多种代码风格，就像是一栋房子的装修中同时出现中式古典风格、现代简约风格、欧式奢华风格以及亚马逊原始风格。抛开美观不谈，这对项目成员间的协作以及后续维护会造成较大的阻碍，所以统一的代码规范是必要的。</p>
<p dir="auto">本规范综合参考<a href="https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/c_sharp_style_guide.html" rel="nofollow ugc">Godot C# Style Guide</a>、微软的<a href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names" rel="nofollow ugc">C# Coding Style</a>与<a href="https://github.com/thomasjacobsen-unity/Unity-Code-Style-Guide" rel="nofollow ugc">Unity Code Style Guide</a>，可作为Godot、Unity、.NET等C#项目代码规范。</p>
<p dir="auto">文中未特别说明部分优先遵循<a href="https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/c_sharp_style_guide.html" rel="nofollow ugc">Godot C# Style Guide</a>，其次遵循微软的<a href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names" rel="nofollow ugc">C# Coding Style</a>。</p>
<h2>格式</h2>
<p dir="auto">本地文件中的换行符在提交到git后应转换为LF，而不是CRLF或CR，一般情况下git默认开启此功能。</p>
<p dir="auto">使用UTF-8无BOM编码，如果使用Visual Studio需要注意设置。</p>
<p dir="auto">使用4个空格作为tab键缩进，一般这是Unity、VSCode、Rider的默认设置，Godot需要在<code>Editor Settings -&gt; Text Editor -&gt; Behavior -&gt; Indent</code>中修改。</p>
<p dir="auto">花括号换行使用Allman风格，而非K&amp;R风格：</p>
<pre><code class="language-C#">while (x == y) 
{
    DoSomething();
    DoSomethingElse();
}

if (x &gt; 0)
{
    DoSomething();
}
</code></pre>
<p dir="auto">内容只有一行时，可省略花括号：</p>
<pre><code class="language-C#">while (x == y) 
    DoSomething();

if (x &gt; 0)
    DoSomething();
</code></pre>
<p dir="auto">属性的get/set方法，以及方法体较为简单时，可写成一行：</p>
<pre><code class="language-C#">public interface MyInterface
{
    int MyProperty { get; set; }
}

public class MyClass : ParentClass
{
    public int Value
    {
        get { return 0; }
        set
        {
            ArrayValue = new [] {value};
        }
    }

    public int Foo() { return GetSomeValue(); }

    public void Bar() =&gt; DoSomething();
}
</code></pre>
<p dir="auto">字段、属性、方法之间的空行不要超过2行。</p>
<p dir="auto">方法内语句之间的空行不要超过2行。</p>
<p dir="auto">保持代码紧凑易阅读，不要无意义空行。</p>
<h2>命名</h2>
<h3>基础</h3>
<p dir="auto">C#代码文件使用PascalCase命名，例如<code>MyClass.cs</code>。</p>
<p dir="auto">不使用默认命名空间，即必须指定类所在的命名空间，命名空间使用PascalCase。</p>
<pre><code class="language-C#">namespace Game 
{
    public class MyClass
    {
    }
}
</code></pre>
<p dir="auto">C# 10.0以上可使用文件范围的命名空间。</p>
<pre><code class="language-C#">namespace Game;

public class MyClass
{
}
</code></pre>
<p dir="auto">命名空间与文件夹结构尽量保持一致，例如<code>namespace Game.Combat.Characters</code>，则其文件夹结构为<code>Game/Combat/Characters</code>。</p>
<p dir="auto">接口使用PascalCase命名，加“I”前缀。</p>
<p dir="auto">接口成员的访问修饰符没有要求，其他地方使用显式访问修饰符。</p>
<pre><code class="language-C#">public interface ITouchable
{
    // 接口成员可省略访问修饰符
    void Interact();
}
</code></pre>
<p dir="auto">枚举使用PascalCase命名，不加任何前缀。</p>
<pre><code class="language-C#">public enum DrinkType
{
    None,
    Soft,
    Hard
}
</code></pre>
<p dir="auto">类与结构体使用PascalCase命名，不加任何前缀，基类可用“BaseXxx”命名但不是硬性要求。</p>
<pre><code class="language-C#">public class SomeClass
{
}
</code></pre>
<p dir="auto">所有常量使用PascalCase命名，无论其访问修饰符是什么，包括局部常量，且<strong>不使用</strong>任何前缀如“k_”。</p>
<pre><code class="language-C#">public class SomeClass
{
    public const float DefaultSpeed = 10f;
    private const string LogTag = "MyClass";
}
</code></pre>
<p dir="auto">所有private字段，无论是否为static，均使用camelCase命名，加下划线前缀，除此之外<strong>不使用</strong>其他前缀如“m_”、“s_”、“t_”等。</p>
<pre><code class="language-C#">public class SomeClass
{
    private static T _instance;
    private static readonly object _lockObj = new();
    private Vector3 _aimingAt;
    private Vector3 _velocity;
}
</code></pre>
<p dir="auto">非private字段使用PascalCase命名。</p>
<pre><code class="language-C#">public class SomeClass
{
    protected int HitPoints;
    internal int State;
    public string Name;
}
</code></pre>
<p dir="auto">所有属性使用PascalCase命名，无论其访问修饰符是什么。</p>
<pre><code class="language-C#">public class SomeClass
{
    private bool IsAlive =&gt; HitPoints &gt; 0;

    protected float MyProperty { get; set; }

    public float AnotherProperty
    {
        get { return MyProperty; }
    }
}
</code></pre>
<p dir="auto">所有方法使用PascalCase命名。</p>
<pre><code class="language-C#">public class SomeClass
{
    public void MyMethod() 
    {
    }
}
</code></pre>
<p dir="auto">局部变量及方法参数使用camelCase命名，不加任何前缀。局部常量使用PascalCase命名。</p>
<pre><code class="language-C#">public float SomeMethod(float someValue) 
{
    const float Increment = 1.2f;
    var result = someValue + Increment;
    return result;
}
</code></pre>
<h3>可读性</h3>
<p dir="auto">含有三个字母及以上的缩写词时，遵循当前命名约定，例如“APIHandler”在PascalCase时写作“ApiHandler”，camelCase时写作“apiHandler”。</p>
<p dir="auto">两个字母的缩写词为特例，例如“UIUtil”在PascalCase时写作“UIUtil”，camelCase时写作“uiUtil”，仅限首字母缩写词，例如“Id”不是首字母缩写。</p>
<p dir="auto">命名应该尽量表达清晰，尽量达到自解释，缩写不要影响可读性，例如：</p>
<pre><code class="language-C#">FindNearbyEnemy()?.Damage(weaponDamage); √

FindNode()?.Change(wpnDmg); ×
</code></pre>
<p dir="auto"><code>bool</code>变量<strong>不加</strong>任何固定的前缀，例如“b”。但推荐使用“is”、“has”等词来表明其含义，例如“isDead”, “isWalking”, "hasDamageMultiplier"。</p>
<p dir="auto">尽量使用动词短语为事件命名，用动词时态区分事件发生的时机。事件不加任何前缀或后缀。</p>
<pre><code class="language-C#">public event Action OpeningDoor;    // 开门事件发生之前
public event Action DoorOpened;     // 开门事件发生之后
</code></pre>
<p dir="auto">事件的接收方法以“On事件名”命名。</p>
<pre><code class="language-C#">public void OnOpeningDoor() 
{
}

public void OnDoorOpened() 
{
}
</code></pre>
<p dir="auto">非特殊情况不使用拼音命名。</p>
<p dir="auto">避免拼写错误，很多时候拼写错误会造成一些让人一时摸不着头脑的Bug（例如JSON序列化、服务端传值错误等等），建议开启编辑器的拼写检查功能。</p>
<h2>示例</h2>
<pre><code class="language-C#">namespace MyGame;

// 类与结构体使用PascalCase命名，不加任何前缀
public class MyClass&lt;T, R&gt; : Parent&lt;T, R&gt; where T : class, new()
{
    // 所有常量使用PascalCase命名
    public const float DefaultSpeed = 10f;
    private const string LogTag = "MyClass";

    // 所有private字段使用camelCase命名，加下划线前缀
    // 使用显式访问修饰符，不省略private
    private static T _instance;
    private static readonly object _lockObj = new();
    private Vector3 _aimingAt;
    private Vector3 _velocity;

    // 非private字段使用PascalCase命名
    protected int HitPoints;
    internal int State;
    public string Name;

    // 所有属性使用PascalCase命名
    private bool IsAlive =&gt; HitPoints &gt; 0;

    protected float MyProperty { get; set; }

    public float AnotherProperty
    {
        get { return MyProperty; }
    }

    public static T Instance
    {
        get
        {
            if (null == _instance)
            {
                lock (_lockObj)
                {
                    _instance ??= new T();
                }
            }
            return _instance;
        }
    }

    // 所有方法使用PascalCase命名
    public void MyMethod()
    {
        int[] values = {1, 2, 3, 4};
        int sum = 0;

        for (int i = 0; i &lt; values.Length; i++)
        {
            switch (i)
            {
                case 3: return;
                default:
                    sum += i &gt; 2 ? 0 : 1;
                    break;
            }
        }

        i += (int)MyProperty;
    }

    // 使用显式访问修饰符，不省略private
    private int MyMethod2() 
    {
        return 0;    
    }
}
</code></pre>
]]></description><link>http://designhub.top/topic/70/自用c-代码规范</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Jul 2026 23:23:20 GMT</lastBuildDate><atom:link href="http://designhub.top/topic/70.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 15 Apr 2024 07:32:04 GMT</pubDate><ttl>60</ttl></channel></rss>