跳转至

C# 编码风格

此文件使用 C# 特定内容扩展 common/coding-style.md。

标准

  • 遵循当前 .NET 约定,启用可空引用类型
  • 对公共和内部 API 优先使用显式访问修饰符
  • 文件按其中定义的主要类型进行组织

类型与模型

  • 对于类似不可变值的模型,优先使用 record 或 record struct
  • 对于具有 ID 和生命周期的实体或类型,使用 class
  • 对于服务边界和抽象,使用 interface
  • 在应用代码中避免使用 dynamic;优先使用泛型或显式模型
public sealed record UserDto(Guid Id, string Email);

public interface IUserRepository
{
    Task<UserDto?> FindByIdAsync(Guid id, CancellationToken cancellationToken);
}

不可变性

  • 对于共享状态,优先使用 init 访问器、构造函数参数和不可变集合
  • 在生成更新后的状态时,不要就地修改输入模型
public sealed record UserProfile(string Name, string Email);

public static UserProfile Rename(UserProfile profile, string name) =>
    profile with { Name = name };

异步与错误处理

  • 优先使用 async/await,而不是 .Result 或 .Wait() 等阻塞调用
  • 通过公共异步 API 传递 CancellationToken
  • 抛出特定异常,并使用结构化属性记录日志
public async Task<Order> LoadOrderAsync(
    Guid orderId,
    CancellationToken cancellationToken)
{
    try
    {
        return await repository.FindAsync(orderId, cancellationToken)
            ?? throw new InvalidOperationException($"Order {orderId} was not found.");
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "Failed to load order {OrderId}", orderId);
        throw;
    }
}

格式化

  • 使用 dotnet format 进行格式化和分析器修复
  • 整理 using 指令,并删除未使用的导入
  • 仅在能保持可读性时优先使用表达式主体成员

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC