# 開發 .NET 應用程式可利用 dotnet format 建立一致的程式碼風格

在團隊開發 .NET 專案時，維持一致且可自動化檢查的程式碼風格是降低溝通與維運成本的關鍵。這篇文章我打算示範 .NET SDK 提供的 `dotnet format` 命令列工具，搭配著 `.editorconfig` 程式碼風格定義檔，在本機與 CI 流程中快速「驗證」與「自動修復」格式問題，讓提交前後都能以同一套規則運作，減少程式碼審查雜訊並提升可讀性與穩定性。

![Image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/5ed72493c79c5f40436f-dotnet-format-image.webp)

### TL;DR

整篇文章基本上就是要介紹 [dotnet format](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format?WT.mc_id=DT-MVP-4015686) 命令的兩種用法：

1.  驗證並檢查風格式否違規
    
    以下命令會根據你專案的 `.editorconfig` 設定，驗證你的 .NET 專案中**所有原始碼檔案**是否存在**格式問題**。因為下達 `--verify-no-changes` 參數的原因，執行的過程並不會自動修復程式碼，且 `--verbosity diagnostic` 會輸出**非常詳細的記錄訊息**，方便理解到底檢查出了哪些問題！
    
    ```bash
    dotnet format --verify-no-changes --verbosity diagnostic
    ```
    
    這個命令執行完畢後，如果有格式完全正確，其**回傳碼**(Exit Code)就會是 `0`，否則就會是非 0 的結果，只要 Exit Code 不為 0 就會自動導致 CI 的 Pipeline 視為「失敗」的結果。
    
2.  自動修復所有格式問題
    
    只要把 `--verify-no-changes` 參數移除，就會「自動修正」所有格式問題，如此一來便可解決團隊大量的時間，也可以大幅增加 Code Review 的品質！👍
    
    ```bash
    dotnet format --verbosity diagnostic
    ```
    

然而 [dotnet format](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format?WT.mc_id=DT-MVP-4015686) 主要參考 `.editorconfig` 程式碼風格定義檔中的定義，該檔案可以透過以下命令自動生成：

```bash
dotnet new editorconfig
```

產生第一版 `.editorconfig` 之後，就可以進一步微調或客製化，你可以參考以下文章：

1.  [使用 Visual Studio 2022 可透過 .editorconfig 鎖定文字檔案的儲存編碼格式](/post/2024/06/07/Visual-Studio-2022-EditorConfig-UTF-8)
2.  [在 Visual Studio 2022 開發 ASP.NET Core 這樣設定就對了！](/post/2024/05/27/Setup-VS2022-for-ASP-NET-Core-Development)
3.  [Overview of .NET source code analysis](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?WT.mc_id=DT-MVP-4015686)

### 常見開發流程

1.  開發人員簽出程式碼，開發完程式且準備要 commit 的時候，先下達以下命令檢查是否格式正確
    
    ```bash
    # 檢查是否有格式錯誤（僅顯示，不自動修正）
    dotnet format --verify-no-changes --verbosity diagnostic
    ```
    
2.  如果發現錯誤，就執行以下命令自動修正所有找到的格式錯誤
    
    ```bash
    dotnet format --verbosity diagnostic
    ```
    
    為求慎重，建議可以再檢查一次格式是否確實修正：
    
    ```bash
    # 檢查是否有格式錯誤（僅顯示，不自動修正）
    dotnet format --verify-no-changes --verbosity diagnostic
    ```
    
3.  將程式碼 Commit 並推送新分支到遠端儲存庫，並且建立 Pull request 準備合併分支
    
4.  透過 CI 自動化檢查
    
    以下使用 GitHub Actions 為例，基本上 `dotnet format` 最好執行在 `dotnet restore` 之後與 `dotnet build` 之前，而且建議不要將多個命令寫在同一個步驟中！
    
    ```yaml
    name: CI Build
    
    on:
      pull_request:
        branches: [ main ]
    
    jobs:
      build:
        name: Build and Package
        runs-on: windows-latest
    
        steps:
        - name: Checkout code
          uses: actions/checkout@v4
    
        - name: Setup .NET 8.0
          uses: actions/setup-dotnet@v4
          with:
            dotnet-version: '8.0.x'
    
        - name: Restore dependencies
          run: dotnet restore
    
        - name: Check code format
          run: dotnet format --verify-no-changes --no-restore
    
        - name: Build
          run: dotnet build --configuration Release --no-restore
    ```
    
    以下是 Azure Pipelines YAML 的範例：
    
    ```yaml
    - task: UseDotNet@2
      displayName: 'Use .NET 8 SDK'
      inputs:
        packageType: 'sdk'
        version: '8.0.x'
        includePreviewVersions: true
    
    - task: DotNetCoreCLI@2
      displayName: 'dotnet-format'
      inputs:
        command: 'custom'
        custom: 'format'
        arguments: '--verify-no-changes'
    ```
    

### 透過 Git Hooks 自動格式化

我們也可以在本機建立 `.git/hooks/pre-commit` 檔案並包含以下內容：

```bash
#!/bin/sh
LC_ALL=C
# Select files to format
FILES=$(git diff --cached --name-only --diff-filter=ACM "*.cs" | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0

# Format all selected files
echo "$FILES" | cat | xargs | sed -e 's/ /,/g' | xargs dotnet format --include

# Add back the modified files to staging
echo "$FILES" | xargs git add

exit 0
```

如此一來就會自動將所有 `*.cs` 檔案的變更都套用 `dotnet format` 自動格式化，就不用怕你的 PR 被退件了！😊

### Rider 設定方式

1.  開啟 `Settings` -> `Tools` -> `File Watchers`
2.  按下「加號」以新增自訂監視器 (`Add a Custom watcher`)
3.  設定一個名稱，例如：`dotnet format on save`
4.  檔案類型：`C#`
5.  範圍：`Open Files`
6.  程式：輸入 `dotnet-format`
7.  引數：`SolutionPath` --verbosity diagnostic --include `FileRelativePath`
8.  (可選) 附加 `--fix-style warning` 以在儲存時自動修正任何樣式問題
9.  (可選) 附加 `--fix-analyzers warning` 以在儲存時自動修正任何分析器警告
10.  停用所有進階選項核取方塊
11.  所有其他值均保留預設值

### 注意事項

-   若要只針對部分檔案處理，可善用 `--include`、`--exclude` 等選項，包含或排除特定目錄
    
    ```bash
    dotnet format --include ./src/ ./tests/ --exclude ./src/submodule-a/
    ```
    
-   可用 `--diagnostics` 修正特定的**程式碼樣式**問題
    
    ```bash
    dotnet format style --diagnostics IDE0005 --severity info
    ```
    
-   其實 `dotnet format` 還有三個**子命令**(Subcommands)，可以更細部分析不同類型的程式碼風格，命令與參數都一樣
    
    ```bash
    # 用 dotnet format style 修正特定的「程式碼樣式」問題
    dotnet format style --diagnostics IDE0005 --severity info
    
    # 用 dotnet format analyzers 修正特定「程式碼分析器」回報的問題：
    dotnet format analyzers --diagnostics CA1831 --severity warn
    
    # 用 dotnet format whitespace 修正「空白字元與換行符號」相關的問題：
    dotnet format whitespace --folder --include ./src/ ./tests/ --exclude ./src/submodule-a/ --verify-no-changes
    ```
    
-   如需進一步以不同嚴重程度(info/warn/error)限定修正或篩選特定問題，可用 `--severity` 與 `--diagnostics` 參數
    

### 相關連結

-   [Welcome to the dotnet-format docs!](https://github.com/dotnet/sdk/tree/main/documentation/format)
-   [dotnet format command - .NET CLI | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format?WT.mc_id=DT-MVP-4015686)
-   [sdk/documentation/format/docs/integrations.md at main · dotnet/sdk](https://github.com/dotnet/sdk/blob/main/documentation/format/docs/integrations.md)
-   [How to enforce .NET format using EditorConfig and GitHub Actions](https://learn.microsoft.com/en-us/community/content/how-to-enforce-dotnet-format-using-editorconfig-github-actions?WT.mc_id=DT-MVP-4015686) 2
