1. 简介
本文档旨在为 C# (.NET) 项目提供一套清晰的大小写命名指导。本规范主要基于 Microsoft 官方的 .NET 设计准则,并结合了业界广泛认可的最佳实践。
2. 核心命名法
所有命名都应基于以下两种大小写风格:
-
PascalCase (帕斯卡命名法): 每个单词的首字母均大写。
示例: ProductService, CalculateTotalPrice
-
camelCase (驼峰命名法): 第一个单词首字母小写,后续单词首字母大写。
示例: productService, calculateTotalPrice
3. 具体命名规则
| 元素类型 | 命名规范 | 示例 | 备注 |
|---|---|---|---|
| 类 (Class) | PascalCase | ProductController, UserService | 名称应为名词或名词短语。 |
| 接口 (Interface) | IPascalCase | IProductRepository, ILogger | 必须以大写字母 I 为前缀。 |
| 枚举 (Enum) | PascalCase | OrderStatus, PaymentMethod | |
| 结构体 (Struct) | PascalCase | Point, Color | |
| 公共成员 (Public Member) | PascalCase | FirstName, GetUserDataAsync() | 包括属性、方法、事件。异步方法以 Async 结尾。 |
| 方法参数 (Parameter) | camelCase | (int customerId, string userName) | |
| 局部变量 (Local Variable) | camelCase | var itemCount = 0; | |
| 私有/保护字段 | _camelCase | _dbContext, _logger | 强烈推荐使用下划线 _ 前缀以区分成员字段。 |
| 常量 (const, static readonly) | PascalCase | MaxPageSize, DefaultConnection | 注意:这与某些语言的全大写规范不同。 |
4. 集合与聚合根 (Aggregate) 命名
在处理一组对象或领域驱动设计 (DDD) 中的聚合时,命名同样需要遵循清晰的规则。
-
普通集合 (Collections):
规范: 使用复数名词,并遵循其作用域的大小写规则。
示例:
// 方法内的局部变量
var users = new List<User>();
// 类的公共属性
public IEnumerable<Product> Products { get; set; }
-
聚合根 (Aggregate Roots):
规范: 聚合根是领域模型的核心,代表一组相关对象的“根”实体。它应使用来自业务领域的单数名词,并采用 PascalCase。
示例:
// Order 是聚合根,它内部包含了 OrderItem 的集合
public class Order
{
public int Id { get; private set; }
public List<OrderItem> Items { get; private set; } = new();
public decimal TotalPrice { get; private set; }
// ... 聚合根包含自身的业务逻辑
public void AddItem(Product product, int quantity)
{
// ... 业务规则检查
}
}
- 注意事项:
- 名称源于业务: 聚合根的名称应直接反映业务术语(领域通用语言),如“订单(Order)”、“客户(Customer)”、“帖子(Post)”。
- 保持单数: 聚合根代表一个独立的业务单元,即使它内部包含集合,其本身也应是单数命名。
-
避坑指南:
误区一:将聚合根与数据表混淆。不要为数据库中的每个表都创建一个所谓的“聚合根”。聚合根是一个业务概念,是数据一致性的边界,而不是数据存储的映射。
误区二:聚合根命名不明确。避免使用 OrderData, OrderModel, OrderEntity 等技术性后缀。直接命名为 Order,其含义应在业务领域中清晰明确。
5. 处理复杂业务与模块化命名
当项目包含多个业务模块,且不同模块可能含有用途相似(如 Request, Response)的类时,必须采用更精确的命名策略以避免混淆。
5.1. 核心原则:使用业务上下文作为前缀/后缀
这是解决模块化命名冲突最直接、最重要的方法。让类名自带上下文信息,从而实现自解释。
规则:[业务实体名][类的用途]
| 类别 | 示例 | 解释 |
|---|---|---|
| 请求 (Request) | CreateUserRequest, UpdateProductRequest | 用于封装创建用户或更新产品的API请求体数据。 |
| 响应 (Response) | OrderResponse, AddressValidationResponse | 用于封装外部API返回的数据。 |
| 数据传输对象 (DTO) | ProductDto, CustomerDetailsDto | 用于在程序内部各层之间传输数据,或作为API的最终返回模型。 |
通过这种方式,OrderResponse 和 AddressResponse 的类名在任何地方都是清晰、无歧义的。
5.2. 结合命名空间进行物理隔离
在遵循核心命名原则的基础上,通过清晰的目录结构和命名空间来组织相关类,可以进一步提升代码的规整性。
示例目录结构:
/Infrastructure
└─── /Clients
├── /OrderApiClient/
│ └── /Models/
│ ├── CreateOrderRequest.cs
│ └── OrderResponse.cs // -> MyProject.Infrastructure.Clients.OrderApiClient.Models
│
└─── /AddressApiClient/
└─── /Models/
├── ValidateAddressRequest.cs
└── AddressResponse.cs // -> MyProject.Infrastructure.Clients.AddressApiClient.Models
5.3. 高级模式:CQRS 命名法
对于业务逻辑极其复杂的场景,可以引入 CQRS (命令查询责任分离) 模式,它能带来极致的命名清晰度。
查询 (Query): 负责读取数据。
查询请求: GetOrderByIdQuery
查询结果: GetOrderByIdQueryResult
命令 (Command): 负责修改数据。
命令请求: SubmitOrderCommand, CancelOrderCommand
这种命名方式将类的具体意图完整地体现在名称中,消除了任何可能的歧义。
6. Web API JSON 序列化规范
6.1. 自动处理 PascalCase 到 camelCase 的转换
问题: 后端 C# 属性遵循 PascalCase,而前端 JavaScript 事实标准为 camelCase。
原则: 后端 C# 代码应始终保持 PascalCase 规范。
解决方案: 在 API 项目启动时,全局配置 JSON 序列化器,使其自动将 PascalCase 属性转换为 camelCase JSON 字段。
在 ASP.NET Core 项目的 Program.cs 文件中添加以下配置:
// Program.cs
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// 自动将 C# 的 PascalCase 属性序列化为 JSON 的 camelCase
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
6.2. 处理特殊的 JSON 命名风格
如果需要与要求特殊命名(如 kebab-case 或 SNAKE_CASE)的第三方系统交互,你有两种方式处理,而无需改变 C# 的命名规范。
方式一:使用 [JsonPropertyName] 特性(推荐) 这是最简单直接的方式,可以针对特定属性覆盖全局策略。
using System.Text.Json.Serialization;
public class LegacySystemDto
{
// 将 C# 的 PascalCase 属性映射到 JSON 的 kebab-case (横杠连接)
[JsonPropertyName("user-id")]
public int UserId { get; set; }
// 将 C# 的 PascalCase 属性映射到 JSON 的 SNAKE_UPPER_CASE (全大写蛇形)
[JsonPropertyName("API_KEY")]
public string ApiKey { get; set; }
// 全局策略仍然生效,此属性会被序列化为 "normalProperty"
public string NormalProperty { get; set; }
}
方式二:创建自定义命名策略(高级) 如果整个 API 都需要遵循一种非标准的命名风格(例如,整个项目都需要输出蛇形命名 snake_case),你可以创建自己的命名策略。
// 1. 创建自定义策略类
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
// 一个将 PascalCase 转换为 snake_case 的简单实现
return string.Concat(name.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower();
}
}
// 2. 在 Program.cs 中注册它
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
// 使用你的自定义策略
options.JsonSerializerOptions.PropertyNamingPolicy = new SnakeCaseNamingPolicy();
});
7. 官方参考资料
.NET 命名准则: docs.microsoft.com/zh-cn/dotne…