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 別名提案的文件。
常見問題
- C# 支援
typedef嗎? 不支援。請使用using別名或真正的型別。 - 別名可以指向 Tuple 嗎? 可以,C# 12 及更新版本支援。
- 別名在每個檔案都有效嗎? 不會,一般別名只在宣告它的檔案中有效。
- 別名會建立新型別嗎? 不會,它參照現有型別。
- 為什麼
using MaybeName = string?;會失敗? 頂層可為 Null 的參考型別禁止作為別名目標。