C# global using 全域引用命名空間

global using 全域引用命名空間

從 C# 10 開始(.NET 6 預設是 C# 10),多了一個 global using 的功能,可以全域引用命名空間,省去幾乎每個 .cs 檔案都要 using 一次的步驟。
    
public class Test1
{
    public static void T1()
    {
        string json = "{\"id\":1,\"name\":\"小明\"}";
        var obj = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
        Console.WriteLine($"id: {obj["id"]}");
        Console.WriteLine($"name: {obj["name"]}");
    }
}
    

上面的程式碼會提示 Cannot resolve symbol 'JsonSerializer' ,我們可以透過在其他 .cs 檔案的 namespace 上方使用 global using 的方式全域引用命名空間。 除了寫在其他 .cs 檔案上以外,常見的做法還有建立一個 Imports.cs, GlobalUsings.cs 或 Using.cs 的空的檔案,然後直接寫在裡面即可,像剛剛 System.Text.Json 就可以建立一個 Imports.cs 檔案,將下面的內容寫入,整個檔案只有一行:
    
global using System.Text.Json;
    

隱含 using

在建立 .NET 6 的控制台應用程式(Console Application)時會發現一開始的 Program.cs 檔案內空空如也,只有兩行程式碼:
    
// See https://aka.ms/new-console-template for more information

Console.WriteLine("Hello, World!");
    

看完上面那個預設範本提供的連結之後就會發現在專案的 .csproj 檔案中有一個選項用來控制自動全域引用命名空間:
    
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    ...
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>
    

在預設啟用的情況下會偷偷的在專案下的 obj\Debug\net6.0\專案名稱.GlobalUsings.g.cs 中自動全域引用命名空間
    
// <auto-generated/>
global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Threading;
global using global::System.Threading.Tasks;

    

如果想要停用則只要把 ImplicitUsings 設定為 disable 即可。

Razor 全域引用命名空間

話說在 ASP.NET Core 的 Razor 中也有類似的功能,也可以透過在 Views 資料夾下的 _ViewImports.cshtml 檔案中 using 命名空間,在其他 .cshtml 檔案中也會自動引用。
    
@using my_app
@using my_app.Models
@using my_app.Enums
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, SmartBreadcrumbs

    

話說為什麼會需要用到「全域引用命名空間」這個功能呢?筆者認為是在開發中越來越注重「整潔架構(Clean Architecture)」的這種「分層架構(Layered Architecture)」模式,為了達到「關注點分離(Separation of concerns,SoC)」,讓軟體更好維護,所以會將內容拆分成不同的層,例如 Infrastructure, Domain, Application 等。所以整個軟體解決方案(Solution)中會有多個類別庫專案(Project)來區分這些不同的層。而不同的層(專案)中要相互使用就需要大量的 using,並且在測試中也是需要同樣大量的 using ,所以才會有 global using 的出現。

延伸閱讀:ASP.NET Core 整潔架構基礎 拆分基礎設施層

參考資料:
Microsoft.Learn - What's new in C# 10
Microsoft.Learn - C# console app template generates top-level statements
Microsoft.Learn - Layout in ASP.NET Core #Importing Shared Directives

留言