clean-code-dotnet

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Clean Code .NET

C#/.NET 整洁代码

Clean Code principles from Robert C. Martin, adapted for C#/.NET. Use as checklist during code reviews and refactoring.
这是适配C#/.NET的Robert C. Martin整洁代码原则,可作为代码评审和重构时的检查清单。

Naming

命名规范

Use Meaningful Names

使用有意义的名称

csharp
// ❌ Bad
int d;
var dataFromDb = db.GetFromService().ToList();

// ✅ Good
int daySinceModification;
var employees = _employeeService.GetEmployees().ToList();
csharp
// ❌ Bad
int d;
var dataFromDb = db.GetFromService().ToList();

// ✅ Good
int daySinceModification;
var employees = _employeeService.GetEmployees().ToList();

Avoid Hungarian Notation

避免匈牙利命名法

csharp
// ❌ Bad
int iCounter;
string strFullName;
public bool IsShopOpen(string pDay, int pAmount) { }

// ✅ Good
int counter;
string fullName;
public bool IsShopOpen(string day, int amount) { }
csharp
// ❌ Bad
int iCounter;
string strFullName;
public bool IsShopOpen(string pDay, int pAmount) { }

// ✅ Good
int counter;
string fullName;
public bool IsShopOpen(string day, int amount) { }

Use Pronounceable Names

使用易读的名称

csharp
// ❌ Bad
public class Employee
{
    public DateTime sWorkDate { get; set; }
    public DateTime modTime { get; set; }
}

// ✅ Good
public class Employee
{
    public DateTime StartWorkingDate { get; set; }
    public DateTime ModificationTime { get; set; }
}
csharp
// ❌ Bad
public class Employee
{
    public DateTime sWorkDate { get; set; }
    public DateTime modTime { get; set; }
}

// ✅ Good
public class Employee
{
    public DateTime StartWorkingDate { get; set; }
    public DateTime ModificationTime { get; set; }
}

Use Domain Names

使用领域相关名称

csharp
// ✅ Good - Use patterns developers know
var singletonObject = SingleObject.GetInstance();
var factory = new PatientFactory();
var repository = new PatientRepository();

csharp
// ✅ Good - 使用开发者熟悉的模式
var singletonObject = SingleObject.GetInstance();
var factory = new PatientFactory();
var repository = new PatientRepository();

Variables

变量规范

Return Early, Avoid Deep Nesting

提前返回,避免深层嵌套

csharp
// ❌ Bad - Deep nesting
public bool IsShopOpen(string day)
{
    if (!string.IsNullOrEmpty(day))
    {
        day = day.ToLower();
        if (day == "friday")
        {
            return true;
        }
        else if (day == "saturday")
        {
            return true;
        }
        // ... more nesting
    }
    return false;
}

// ✅ Good - Guard clauses + early return
public bool IsShopOpen(string day)
{
    if (string.IsNullOrEmpty(day))
        return false;

    var openingDays = new[] { "friday", "saturday", "sunday" };
    return openingDays.Contains(day.ToLower());
}
csharp
// ❌ Bad - 深层嵌套
public bool IsShopOpen(string day)
{
    if (!string.IsNullOrEmpty(day))
    {
        day = day.ToLower();
        if (day == "friday")
        {
            return true;
        }
        else if (day == "saturday")
        {
            return true;
        }
        // ... 更多嵌套
    }
    return false;
}

// ✅ Good - 卫语句 + 提前返回
public bool IsShopOpen(string day)
{
    if (string.IsNullOrEmpty(day))
        return false;

    var openingDays = new[] { "friday", "saturday", "sunday" };
    return openingDays.Contains(day.ToLower());
}

Avoid Magic Strings

避免魔法字符串

csharp
// ❌ Bad
if (userRole == "Admin") { }

// ✅ Good
const string AdminRole = "Admin";
if (userRole == AdminRole) { }

// ✅ Better - Use enum
public enum UserRole { Admin, User, Guest }
if (userRole == UserRole.Admin) { }
csharp
// ❌ Bad
if (userRole == "Admin") { }

// ✅ Good
const string AdminRole = "Admin";
if (userRole == AdminRole) { }

// ✅ 更优 - 使用枚举
public enum UserRole { Admin, User, Guest }
if (userRole == UserRole.Admin) { }

Don't Add Unneeded Context

不要添加冗余上下文

csharp
// ❌ Bad - Redundant prefix
public class Car
{
    public string CarMake { get; set; }
    public string CarModel { get; set; }
    public string CarColor { get; set; }
}

// ✅ Good
public class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public string Color { get; set; }
}
csharp
// ❌ Bad - 冗余前缀
public class Car
{
    public string CarMake { get; set; }
    public string CarModel { get; set; }
    public string CarColor { get; set; }
}

// ✅ Good
public class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public string Color { get; set; }
}

Use Default Arguments

使用默认参数

csharp
// ❌ Bad
public void CreateMicrobrewery(string name = null)
{
    var breweryName = !string.IsNullOrEmpty(name) ? name : "Hipster Brew Co.";
}

// ✅ Good
public void CreateMicrobrewery(string breweryName = "Hipster Brew Co.")
{
    // breweryName is always valid
}

csharp
// ❌ Bad
public void CreateMicrobrewery(string name = null)
{
    var breweryName = !string.IsNullOrEmpty(name) ? name : "Hipster Brew Co.";
}

// ✅ Good
public void CreateMicrobrewery(string breweryName = "Hipster Brew Co.")
{
    // breweryName始终有效
}

Functions

函数规范

Functions Should Do One Thing

函数单一职责

csharp
// ❌ Bad - Multiple responsibilities
public void SendEmailToListOfClients(string[] clients)
{
    foreach (var client in clients)
    {
        var clientRecord = db.Find(client);
        if (clientRecord.IsActive())
        {
            Email(client);
        }
    }
}

// ✅ Good - Single responsibility
public void SendEmailToActiveClients(string[] clients)
{
    var activeClients = GetActiveClients(clients);
    activeClients.ForEach(client => Email(client));
}

public List<Client> GetActiveClients(string[] clients)
{
    return db.Find(clients).Where(c => c.IsActive).ToList();
}
csharp
// ❌ Bad - 多职责
public void SendEmailToListOfClients(string[] clients)
{
    foreach (var client in clients)
    {
        var clientRecord = db.Find(client);
        if (clientRecord.IsActive())
        {
            Email(client);
        }
    }
}

// ✅ Good - 单一职责
public void SendEmailToActiveClients(string[] clients)
{
    var activeClients = GetActiveClients(clients);
    activeClients.ForEach(client => Email(client));
}

public List<Client> GetActiveClients(string[] clients)
{
    return db.Find(clients).Where(c => c.IsActive).ToList();
}

Avoid Side Effects

避免副作用

csharp
// ❌ Bad - Modifies global state
var name = "Ryan McDermott";

public void SplitAndEnrichFullName()
{
    var temp = name.Split(" ");
    name = $"First: {temp[0]}, Last: {temp[1]}"; // Side effect!
}

// ✅ Good - Pure function
public string SplitAndEnrichFullName(string name)
{
    var temp = name.Split(" ");
    return $"First: {temp[0]}, Last: {temp[1]}";
}
csharp
// ❌ Bad - 修改全局状态
var name = "Ryan McDermott";

public void SplitAndEnrichFullName()
{
    var temp = name.Split(" ");
    name = $"First: {temp[0]}, Last: {temp[1]}"; // 副作用!
}

// ✅ Good - 纯函数
public string SplitAndEnrichFullName(string name)
{
    var temp = name.Split(" ");
    return $"First: {temp[0]}, Last: {temp[1]}";
}

Avoid Negative Conditionals

避免否定条件

csharp
// ❌ Bad
public bool IsDOMNodeNotPresent(string node) { }
if (!IsDOMNodeNotPresent(node)) { }  // Double negative!

// ✅ Good
public bool IsDOMNodePresent(string node) { }
if (IsDOMNodePresent(node)) { }
csharp
// ❌ Bad
public bool IsDOMNodeNotPresent(string node) { }
if (!IsDOMNodeNotPresent(node)) { }  // 双重否定!

// ✅ Good
public bool IsDOMNodePresent(string node) { }
if (IsDOMNodePresent(node)) { }

Avoid Flag Parameters

避免标志参数

csharp
// ❌ Bad - Flag indicates multiple responsibilities
public void CreateFile(string name, bool temp = false)
{
    if (temp)
        Touch("./temp/" + name);
    else
        Touch(name);
}

// ✅ Good - Separate methods
public void CreateFile(string name) => Touch(name);
public void CreateTempFile(string name) => Touch("./temp/" + name);
csharp
// ❌ Bad - 标志参数表示多职责
public void CreateFile(string name, bool temp = false)
{
    if (temp)
        Touch("./temp/" + name);
    else
        Touch(name);
}

// ✅ Good - 拆分方法
public void CreateFile(string name) => Touch(name);
public void CreateTempFile(string name) => Touch("./temp/" + name);

Limit Function Arguments (2 or fewer)

限制函数参数(最多2个)

csharp
// ❌ Bad
public void CreateMenu(string title, string body, string buttonText, bool cancellable) { }

// ✅ Good - Use object
public class MenuConfig
{
    public string Title { get; set; }
    public string Body { get; set; }
    public string ButtonText { get; set; }
    public bool Cancellable { get; set; }
}

public void CreateMenu(MenuConfig config) { }
csharp
// ❌ Bad
public void CreateMenu(string title, string body, string buttonText, bool cancellable) { }

// ✅ Good - 使用对象
public class MenuConfig
{
    public string Title { get; set; }
    public string Body { get; set; }
    public string ButtonText { get; set; }
    public bool Cancellable { get; set; }
}

public void CreateMenu(MenuConfig config) { }

Encapsulate Conditionals

封装条件判断

csharp
// ❌ Bad
if (article.state == "published") { }

// ✅ Good
if (article.IsPublished()) { }
csharp
// ❌ Bad
if (article.state == "published") { }

// ✅ Good
if (article.IsPublished()) { }

Remove Dead Code

删除无用代码

csharp
// ❌ Bad
public void OldRequestModule(string url) { }  // Unused!
public void NewRequestModule(string url) { }

var request = NewRequestModule(requestUrl);

// ✅ Good - Delete unused code
public void RequestModule(string url) { }

var request = RequestModule(requestUrl);

csharp
// ❌ Bad
public void OldRequestModule(string url) { }  // 未使用!
public void NewRequestModule(string url) { }

var request = NewRequestModule(requestUrl);

// ✅ Good - 删除未使用代码
public void RequestModule(string url) { }

var request = RequestModule(requestUrl);

SOLID Principles

SOLID原则

Single Responsibility (SRP)

单一职责原则(SRP)

csharp
// ❌ Bad - Two responsibilities
class UserSettings
{
    public void ChangeSettings(Settings settings)
    {
        if (VerifyCredentials()) { /* ... */ }
    }

    private bool VerifyCredentials() { /* ... */ }  // Auth responsibility
}

// ✅ Good - Separated
class UserAuth
{
    public bool VerifyCredentials() { /* ... */ }
}

class UserSettings
{
    private readonly UserAuth _auth;

    public void ChangeSettings(Settings settings)
    {
        if (_auth.VerifyCredentials()) { /* ... */ }
    }
}
csharp
// ❌ Bad - 两个职责
class UserSettings
{
    public void ChangeSettings(Settings settings)
    {
        if (VerifyCredentials()) { /* ... */ }
    }

    private bool VerifyCredentials() { /* ... */ }  // 认证职责
}

// ✅ Good - 职责分离
class UserAuth
{
    public bool VerifyCredentials() { /* ... */ }
}

class UserSettings
{
    private readonly UserAuth _auth;

    public void ChangeSettings(Settings settings)
    {
        if (_auth.VerifyCredentials()) { /* ... */ }
    }
}

Open/Closed (OCP)

开闭原则(OCP)

csharp
// ❌ Bad - Must modify to extend
class HttpRequester
{
    public bool Fetch(string url)
    {
        if (adapterName == "ajaxAdapter")
            return MakeAjaxCall(url);
        else if (adapterName == "httpNodeAdapter")
            return MakeHttpCall(url);
        // Must add more else-if for new adapters!
    }
}

// ✅ Good - Open for extension, closed for modification
interface IAdapter
{
    bool Request(string url);
}

class AjaxAdapter : IAdapter
{
    public bool Request(string url) { /* ... */ }
}

class HttpRequester
{
    private readonly IAdapter _adapter;
    public bool Fetch(string url) => _adapter.Request(url);
}
csharp
// ❌ Bad - 扩展需修改原有代码
class HttpRequester
{
    public bool Fetch(string url)
    {
        if (adapterName == "ajaxAdapter")
            return MakeAjaxCall(url);
        else if (adapterName == "httpNodeAdapter")
            return MakeHttpCall(url);
        // 添加新适配器需新增更多else-if!
    }
}

// ✅ Good - 对扩展开放,对修改关闭
interface IAdapter
{
    bool Request(string url);
}

class AjaxAdapter : IAdapter
{
    public bool Request(string url) { /* ... */ }
}

class HttpRequester
{
    private readonly IAdapter _adapter;
    public bool Fetch(string url) => _adapter.Request(url);
}

Liskov Substitution (LSP)

里氏替换原则(LSP)

csharp
// ❌ Bad - Square breaks Rectangle behavior
class Square : Rectangle
{
    public override void SetWidth(double width) { Width = Height = width; }
}

// ✅ Good - Use abstraction
abstract class Shape
{
    public abstract double GetArea();
}

class Rectangle : Shape { /* ... */ }
class Square : Shape { /* ... */ }
csharp
// ❌ Bad - Square破坏了Rectangle的行为
class Square : Rectangle
{
    public override void SetWidth(double width) { Width = Height = width; }
}

// ✅ Good - 使用抽象
abstract class Shape
{
    public abstract double GetArea();
}

class Rectangle : Shape { /* ... */ }
class Square : Shape { /* ... */ }

Interface Segregation (ISP)

接口隔离原则(ISP)

csharp
// ❌ Bad - Robot can't eat but must implement
interface IEmployee { void Work(); void Eat(); }

class Robot : IEmployee
{
    public void Work() { /* ... */ }
    public void Eat() { /* Robot can't eat! */ }
}

// ✅ Good - Segregated interfaces
interface IWorkable { void Work(); }
interface IFeedable { void Eat(); }

class Human : IWorkable, IFeedable { /* ... */ }
class Robot : IWorkable { /* ... */ }
csharp
// ❌ Bad - Robot无法Eat但必须实现
interface IEmployee { void Work(); void Eat(); }

class Robot : IEmployee
{
    public void Work() { /* ... */ }
    public void Eat() { /* Robot无法进食! */ }
}

// ✅ Good - 接口隔离
interface IWorkable { void Work(); }
interface IFeedable { void Eat(); }

class Human : IWorkable, IFeedable { /* ... */ }
class Robot : IWorkable { /* ... */ }

Dependency Inversion (DIP)

依赖倒置原则(DIP)

csharp
// ❌ Bad - Depends on concrete types
class Manager
{
    private readonly Robot _robot;
    private readonly Human _human;
}

// ✅ Good - Depends on abstractions
class Manager
{
    private readonly IEnumerable<IEmployee> _employees;

    public Manager(IEnumerable<IEmployee> employees)
    {
        _employees = employees;
    }
}
csharp
// ❌ Bad - 依赖具体类型
class Manager
{
    private readonly Robot _robot;
    private readonly Human _human;
}

// ✅ Good - 依赖抽象
class Manager
{
    private readonly IEnumerable<IEmployee> _employees;

    public Manager(IEnumerable<IEmployee> employees)
    {
        _employees = employees;
    }
}

Constructor Dependency Smell (SRP Indicator)

构造函数依赖异味(SRP指示器)

Too many constructor dependencies indicate SRP violation:
csharp
// ❌ Code Smell: 15 dependencies = too many responsibilities!
public class LicensePlateAppService : ApplicationService
{
    public LicensePlateAppService(
        IRepository<LicensePlate, Guid> licensePlateRepository,
        IRepository<LicensePlateWithoutTag, Guid> licensePlateWithoutTagRepository,
        IRepository<ASN, Guid> asnRepository,
        IRepository<Project, Guid> projectRepository,
        IRepository<Tag, Guid> tagRepository,
        IRepository<SKU, Guid> skuRepository,
        IRepository<Customer, Guid> customerRepository,
        IRepository<LicensePlateHold, Guid> licensePlateHoldRepository,
        IRepository<LicensePlateLocation, Guid> licensePlateLocationRepository,
        IRepository<Location, Guid> locationRepository,
        IWarehouseAppService warehouseAppService,
        IWarehouseOwnerAppService warehouseOwnerAppService,
        IBlobContainer<BulkUpdateLPExcelFileContainer> fileContainer,
        LicensePlateService.LicensePlateServiceClient licensePlateServiceClient,
        CommonDependencies<LicensePlateAppService> commonDependencies)
    { }
}

// ✅ Good: Split by responsibility
public class LicensePlateAppService { }      // CRUD only (~5 deps)
public class LicensePlateBulkService { }     // Bulk imports (~4 deps)
public class LicensePlateEventPublisher { }  // Events (~3 deps)
Dependency Count Guidelines:
DependenciesStatusAction
1-5✅ NormalAcceptable
6-8⚠️ WarningReview for splitting opportunities
9+❌ SmellRefactor required - class has too many responsibilities
Refactoring Strategies:
  1. Extract Service - Move related operations to a dedicated service
  2. Facade Pattern - Group related dependencies behind a facade
  3. Domain Events - Decouple via publish/subscribe instead of direct calls
  4. Mediator Pattern - Use MediatR to reduce direct dependencies

过多的构造函数依赖表明违反了单一职责原则:
csharp
// ❌ 代码异味:15个依赖 = 职责过多!
public class LicensePlateAppService : ApplicationService
{
    public LicensePlateAppService(
        IRepository<LicensePlate, Guid> licensePlateRepository,
        IRepository<LicensePlateWithoutTag, Guid> licensePlateWithoutTagRepository,
        IRepository<ASN, Guid> asnRepository,
        IRepository<Project, Guid> projectRepository,
        IRepository<Tag, Guid> tagRepository,
        IRepository<SKU, Guid> skuRepository,
        IRepository<Customer, Guid> customerRepository,
        IRepository<LicensePlateHold, Guid> licensePlateHoldRepository,
        IRepository<LicensePlateLocation, Guid> licensePlateLocationRepository,
        IRepository<Location, Guid> locationRepository,
        IWarehouseAppService warehouseAppService,
        IWarehouseOwnerAppService warehouseOwnerAppService,
        IBlobContainer<BulkUpdateLPExcelFileContainer> fileContainer,
        LicensePlateService.LicensePlateServiceClient licensePlateServiceClient,
        CommonDependencies<LicensePlateAppService> commonDependencies)
    { }
}

// ✅ Good: 按职责拆分
public class LicensePlateAppService { }      // 仅CRUD(约5个依赖)
public class LicensePlateBulkService { }     // 批量导入(约4个依赖)
public class LicensePlateEventPublisher { }  // 事件处理(约3个依赖)
依赖数量指南:
依赖数量状态操作
1-5✅ 正常可接受
6-8⚠️ 警告检查是否有拆分机会
9+❌ 异味必须重构 - 类职责过多
重构策略:
  1. 提取服务 - 将相关操作移至专用服务
  2. 外观模式 - 将相关依赖封装在外观类后
  3. 领域事件 - 通过发布/订阅解耦,而非直接调用
  4. 中介者模式 - 使用MediatR减少直接依赖

Error Handling

错误处理

Don't Use
throw ex

不要使用
throw ex

csharp
// ❌ Bad - Loses stack trace
catch (Exception ex)
{
    logger.LogError(ex);
    throw ex;  // Stack trace lost!
}

// ✅ Good - Preserves stack trace
catch (Exception ex)
{
    logger.LogError(ex);
    throw;  // Rethrows with original stack
}

// ✅ Also Good - Wrap with inner exception
catch (Exception ex)
{
    throw new BusinessException("Operation failed", ex);
}
csharp
// ❌ Bad - 丢失堆栈跟踪
catch (Exception ex)
{
    logger.LogError(ex);
    throw ex;  // 堆栈跟踪丢失!
}

// ✅ Good - 保留堆栈跟踪
catch (Exception ex)
{
    logger.LogError(ex);
    throw;  // 重新抛出并保留原始堆栈
}

// ✅ 同样推荐 - 包装为内部异常
catch (Exception ex)
{
    throw new BusinessException("操作失败", ex);
}

Don't Ignore Caught Errors

不要忽略捕获的错误

csharp
// ❌ Bad - Silent swallow
catch (Exception ex) { }  // Never do this!

// ✅ Good - Handle or propagate
catch (Exception ex)
{
    _logger.LogError(ex, "Operation failed");
    throw;  // Or handle appropriately
}
csharp
// ❌ Bad - 静默吞掉异常
catch (Exception ex) { }  // 绝对不要这样做!

// ✅ Good - 处理或传播异常
catch (Exception ex)
{
    _logger.LogError(ex, "操作失败");
    throw;  // 或进行适当处理
}

Use Multiple Catch Blocks

使用多个Catch块

csharp
// ❌ Bad - Type checking in catch
catch (Exception ex)
{
    if (ex is TaskCanceledException) { /* ... */ }
    else if (ex is TaskSchedulerException) { /* ... */ }
}

// ✅ Good - Separate catch blocks
catch (TaskCanceledException ex)
{
    // Handle cancellation
}
catch (TaskSchedulerException ex)
{
    // Handle scheduler error
}

csharp
// ❌ Bad - 在Catch中进行类型检查
catch (Exception ex)
{
    if (ex is TaskCanceledException) { /* ... */ }
    else if (ex is TaskSchedulerException) { /* ... */ }
}

// ✅ Good - 分离Catch块
catch (TaskCanceledException ex)
{
    // 处理取消操作
}
catch (TaskSchedulerException ex)
{
    // 处理调度器错误
}

Comments

注释规范

Avoid Positional Markers and Regions

避免位置标记和Regions

csharp
// ❌ Bad
#region Scope Model Instantiation
var model = new Model();
#endregion

#region Action setup
void Actions() { }
#endregion

// ✅ Good - Let code speak
var model = new Model();

void Actions() { }
csharp
// ❌ Bad
#region Scope Model Instantiation
var model = new Model();
#endregion

#region Action setup
void Actions() { }
#endregion

// ✅ Good - 让代码自解释
var model = new Model();

void Actions() { }

Don't Leave Commented Code

不要保留注释掉的代码

csharp
// ❌ Bad
DoStuff();
// DoOtherStuff();
// DoSomeMoreStuff();

// ✅ Good - Use version control
DoStuff();
csharp
// ❌ Bad
DoStuff();
// DoOtherStuff();
// DoSomeMoreStuff();

// ✅ Good - 利用版本控制系统
DoStuff();

Only Comment Business Logic Complexity

仅对复杂业务逻辑添加注释

csharp
// ❌ Bad - Obvious comments
var hash = 0;  // The hash
var length = data.Length;  // Length of string

// ✅ Good - Explains WHY, not WHAT
// Using djb2 hash for good speed/collision tradeoff
hash = ((hash << 5) - hash) + character;

csharp
// ❌ Bad - 冗余注释
var hash = 0;  // 哈希值
var length = data.Length;  // 字符串长度

// ✅ Good - 解释原因,而非执行逻辑
// 使用djb2哈希算法,兼顾速度和冲突率
hash = ((hash << 5) - hash) + character;

Quick Reference Checklist

快速参考检查清单

Code Review Checklist

代码评审检查清单

  • Naming: Meaningful, pronounceable, no Hungarian
  • Functions: Single responsibility, <3 args, no flags
  • Variables: No magic strings, early returns, no nesting >2
  • SOLID: Interfaces over concrete, small focused classes
  • Dependencies: Constructor has <8 dependencies (SRP indicator)
  • Error Handling: No
    throw ex
    , no silent catch, specific exception types
  • Comments: No regions, no dead code, explains WHY

  • 命名:有意义、易读、无匈牙利命名法
  • 函数:单一职责、参数少于3个、无标志参数
  • 变量:无魔法字符串、提前返回、嵌套不超过2层
  • SOLID:优先使用接口而非具体实现、类职责单一
  • 依赖:构造函数依赖少于8个(SRP指示器)
  • 错误处理:不使用
    throw ex
    、不静默吞异常、使用特定异常类型
  • 注释:无Regions、无注释掉的代码、仅注释复杂业务逻辑

References

参考资料

  • references/solid-principles.md: Full SOLID examples
  • references/async-patterns.md: Async/await guidelines
  • references/editorconfig-template.md: .editorconfig template
  • references/solid-principles.md:完整SOLID示例
  • references/async-patterns.md:Async/await指南
  • references/editorconfig-template.md:.editorconfig模板