C# 标识符命名规则和约定

标识符 是分配给类型(类、接口、结构、委托或枚举)、成员、变量或命名空间的名称。

命名规则

有效标识符必须遵循这些规则。 C# 编译器为不遵循以下规则的任何标识符生成错误:

  • 标识符必须以字母或下划线开头(_)。
  • 标识符可以包含 Unicode 字母字符、十进制数字字符、Unicode 连接字符、Unicode 组合字符或 Unicode 格式字符。 有关 Unicode 类别的详细信息,请参阅 Unicode 类别数据库

可以使用标识符上的 @ 前缀来声明与 C# 关键字匹配的标识符。 @ 不是标识符名称的一部分。 例如,@if 声明名为 if的标识符。 这些 逐字标识符 主要用于与其他语言声明的标识符的互作性。

有关有效标识符的完整定义,请参阅 C# 语言规范 中的标识符文章。

重要

C# 语言规范 仅允许字母(Lu、Ll、Lt、Lm 或 Nl)、数字(Nd)、连接(Pc)、组合(Mn 或 Mc)和格式设置(Cf)类别。 除此之外的任何内容都会自动使用 _ 替换。 这可能会影响某些 Unicode 字符。

命名约定

除了规则之外,标识符名称的约定还在整个 .NET API 中使用。 这些约定为名称提供一致性,但编译器不会强制执行它们。 可以在项目中自由使用不同的约定。

按照约定,C# 程序对类型名称、命名空间和所有公共成员使用 PascalCase。 此外,dotnet/docs 团队使用从 .NET Runtime 团队的编码风格中吸收的以下约定:

  • 接口名称以大写 I开头。

  • 属性类型以单词 Attribute结尾。

  • 枚举类型对非标记使用单数名词,对标记使用复数名词。

  • 标识符不应包含两个连续下划线(_)字符。 这些名称是为编译器生成的标识符保留的。

  • 对变量、方法和类使用有意义的描述性名称。

  • 清晰胜于简洁。。

  • 将 PascalCase 用于类名和方法名称。

  • 对方法参数和局部变量使用驼峰式大小写。

  • 将 PascalCase 用于常量名,包括字段和局部常量。

  • 专用实例字段以下划线 (_) 开头,其余文本为驼峰式大小写。

  • 静态字段以 s_开头。 此约定不是默认的 Visual Studio 行为,也不是 框架设计准则的一部分,而是在编辑器配置 可配置的。

  • 避免在名称中使用缩写或首字母缩略词,但广为人知和接受的缩写除外。

  • 使用遵循反向域名表示法的有意义的描述性命名空间。

  • 选择表示程序集的主要用途的程序集名称。

  • 避免使用单字母名称,但简单循环计数器除外。 此外,描述 C# 构造语法的语法示例通常使用以下与 C# 语言规范中使用的约定匹配的以下单字母名称。 语法示例是规则的例外。

    • S 用于结构,C 用于类。
    • 使用 M 来表示方法。
    • 对变量使用 v,对参数使用 p
    • r 用于 ref 参数。

提示

可以使用 代码样式命名规则强制实施涉及大写、前缀、后缀和单词分隔符的命名约定。

在以下示例中,与标记为 public 的元素相关的指南在处理 protectedprotected internal 元素时也适用,所有这些元素都对外部调用方可见。

Pascal 案例

在命名 classinterfacestructdelegate 类型时,使用 Pascal 大小写(“PascalCasing”)。

public class DataService
{
}
public record PhysicalAddress(
    string Street,
    string City,
    string StateOrProvince,
    string ZipCode);
public struct ValueCoordinate
{
}
public delegate void DelegateType(string message);

命名 interface 时,使用 pascal 大小写并在名称前面加上前缀 I。 此前缀可以清楚地向使用者表明这是 interface

public interface IWorkerQueue
{
}

在命名字段、属性和事件等类型的 public 成员时,使用 pascal 大小写。 此外,对所有方法和本地函数使用 pascal 大小写。

public class ExampleEvents
{
    // A public field, these should be used sparingly
    public bool IsValid;

    // An init-only property
    public IWorkerQueue WorkerQueue { get; init; }

    // An event
    public event Action EventProcessing;

    // Method
    public void StartEventProcessing()
    {
        // Local function
        static int CountQueueItems() => WorkerQueue.Count;
        // ...
    }
}

在编写位置记录时,请使用帕斯卡命名法来设定参数,因为这些参数是记录的公共属性。

public record PhysicalAddress(
    string Street,
    string City,
    string StateOrProvince,
    string ZipCode);

有关位置记录的详细信息,请参阅 属性定义的位置语法。

驼峰式大小写

在命名 privateinternal 字段时,使用驼峰式大小写(“camelCasing”),并对它们添加 _ 作为前缀。 命名局部变量(包括委托类型的实例)时,请使用驼峰式大小写。

public class DataService
{
    private IWorkerQueue _workerQueue;
}

提示

在支持语句完成的 IDE 中编辑遵循这些命名约定的 C# 代码时,键入 _ 将显示所有对象范围成员。

使用为 privateinternalstatic 字段时 请使用 s_ 前缀,对于线程静态,请使用 t_

public class DataService
{
    private static IWorkerQueue s_workerQueue;

    [ThreadStatic]
    private static TimeSpan t_timeSpan;
}

编写方法参数时,请使用驼峰式大小写。

public T SomeMethod<T>(int someNumber, bool isValid)
{
}

有关 C# 命名约定的详细信息,请参阅 .NET 运行时团队的编码风格

类型参数命名准则

以下准则适用于泛型类型参数上的类型参数。 类型参数是泛型类型或泛型方法中参数的占位符。 可以在 C# 编程指南中详细了解 泛型类型参数

  • 请使用描述性名称命名泛型类型参数,除非单个字母名称完全具有自我说明性且描述性名称不会增加任何作用。

    public interface ISessionChannel<TSession> { /*...*/ }
    public delegate TOutput Converter<TInput, TOutput>(TInput from);
    public class List<T> { /*...*/ }
    
  • 对具有单个字母类型参数的类型,考虑 使用 T 作为类型参数名称。

    public int IComparer<T>() => 0;
    public delegate bool Predicate<T>(T item);
    public struct Nullable<T> where T : struct { /*...*/ }
    
  • 在类型参数描述性名称前添加前缀"T"。

    public interface ISessionChannel<TSession>
    {
        TSession Session { get; }
    }
    
  • 考虑在参数名称中指示出类型参数的约束。 例如,限制为 ISession 的参数可能被称为 TSession

代码分析规则 CA1715 可用于确保正确命名类型参数。

额外的命名约定

  • 在不包括 using 指令的示例中,使用命名空间限定。 如果您知道在项目中默认导入了某个命名空间,那么就不需要对该命名空间中的名称进行完全限定。 如果对于单行来说过长,则可以在点 (.) 后中断限定名称,如下面的示例所示。

    var currentPerformanceCounterCategory = new System.Diagnostics.
        PerformanceCounterCategory();
    
  • 无需更改使用 Visual Studio 设计器工具创建的对象的名称,使其符合其他准则。