HOWTO · Csharp

C# 中 typedef 的等效寫法

使用 using 別名實作 C# 中的 typedef 等效寫法,了解 C# 12 的 Tuple 別名與一般泛型型別別名。

本頁內容

C# 沒有 typedef 關鍵字。最接近的功能是 using 別名,可以為現有命名空間或型別指定檔案範圍內使用的名稱。

別名能提升可讀性,但不會在執行階段建立新型別。如果需要具有獨立行為或驗證邏輯的型別,請定義類別、record 或結構。

為現有型別使用 using 別名

將別名放在檔案頂端、其他 using 指示詞旁邊,並使用完全限定的目標型別。如此別名不會依賴其他 using 指示詞。

例如,using RouteTable = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>; 為現有的封閉泛型型別指定名稱。

RouteTable 只是 Dictionary<string, List<int>> 的較短寫法。它不會增加型別安全性,也不會建立新宣告。一般別名只在宣告它的原始檔中有效,不會自動套用到整個專案。

不同形式的 using 有不同作用:using System.Text; 匯入命名空間,using static System.Math; 匯入靜態成員,而 using RouteTable = ...; 建立別名。

C# 12 的 Tuple 別名與泛型型別別名

C# 12 擴充了 using 別名,使它能指向 Tuple 等先前無法命名的型別。具名型別與建構泛型型別的一般別名在 C# 12 之前就已支援。以下範例同時使用這兩種形式:

using RouteTable = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>;
using Coordinate = (double Latitude, double Longitude);

RouteTable routes = new() { ["home"] = [1, 2] };
Coordinate point = (52.37, 4.90);

System.Console.WriteLine($"{routes["home"].Count}:{point.Latitude:F2}");
2:52.37

這個成功案例在隔離且停用網路的 .NET 10.0.401 環境中完成還原與建置。專案被複製到容器的暫存儲存空間,使用 --ignore-failed-sources 還原後執行,原始 fixture 與映像都未變更。

如果專案使用 C# 11 或更早版本,不要假設任意型別形式的別名都能編譯。請升級工具鏈或直接寫出完整型別。具名型別的別名早於 C# 12。

別名不會做什麼

別名不是類似 typedef 的獨立型別。RouteTable 與完整的 Dictionary 型別在編譯時可以互換。如果不希望某個值被誤傳為另一個值,應使用 record 或結構等真正的領域型別。

同樣地,Tuple 別名只是為 Tuple 形狀提供易讀名稱,不會將它變成具名類別。元素名稱有助於存取與文件說明,但不會提供獨立的型別識別。

可為 Null 參考別名目標的邊界

擴充後的別名語法仍有限制。頂層可為 Null 的參考型別不能作為別名目標,因此 using MaybeName = string?; 是刻意設定的無效宣告。

編譯器會拒絕該宣告,因為 string? 是可為 Null 的參考註記,不是此位置允許的別名目標。邊界 fixture 應該編譯失敗;它是診斷證據,不是可執行的解決方案。

何時定義真正的型別

當名稱需要代表獨立概念時,請選擇類別、record 或結構。需要不變條件、驗證、方法、受控建構、相等語意或公開 API 時,真正的型別更合適。只想縮短檔案內長型別寫法時,使用別名即可。

請參閱 Microsoft 關於 using 指示詞、C# 12 與 using 別名提案的文件。

常見問題

  1. C# 支援 typedef 嗎? 不支援。請使用 using 別名或真正的型別。
  2. 別名可以指向 Tuple 嗎? 可以,C# 12 及更新版本支援。
  3. 別名在每個檔案都有效嗎? 不會,一般別名只在宣告它的檔案中有效。
  4. 別名會建立新型別嗎? 不會,它參照現有型別。
  5. 為什麼 using MaybeName = string?; 會失敗? 頂層可為 Null 的參考型別禁止作為別名目標。