匿名類型的型別名稱僅存在編譯期,執行期無法在原始碼中直接參考。這導致跨方法傳遞時只能用 object 或 dynamic,失去強型別優勢。但利用編譯器對相同結構匿名類型產生單一型別的特性,我們可以透過泛型方法實現「強制轉型回強型別」。
同一組件中,屬性名稱、型別、順序完全相同的匿名類型初始化器,編譯器會重用同一個產生型別。因此,若我們能在呼叫端建立一個「樣本實例」傳給泛型方法,方法內即可將 object 轉型為該具體匿名型別。
public static T CastAnonymous<T>(object anonymous, T sample)
{
return (T)anonymous;
}
public class User
{
public string Name { get; set; }
}
public static void Main()
{
var user = new User { Name = "Lucifer" };
// 建立匿名類型實例
var anon = new { Age = 26, UserName = user.Name, IsActive = false };
// 傳遞為 object
ProcessAnon(anon);
}
public static void ProcessAnon(object anonymous)
{
// 在此建立「結構相同」的樣本,讓編譯器產生相同型別
var sample = new { Age = 0, UserName = "", IsActive = false };
// 強制轉型回強型別
var typed = CastAnonymous(anonymous, sample);
// 現在擁有完整 IntelliSense 與強型別存取
Console.WriteLine($"{typed.Age} - {typed.UserName} - {typed.IsActive}");
}
sample 參數值不被使用,僅提供給編譯器推斷 T 為目標匿名型別。InvalidCastException。dynamic,雖失去編譯期檢查但更靈活。此技巧屬於進階 Hack,適用於:
生產代碼慎用: 結構變更極易導致執行期崩潰,且降低代碼可讀性。現代 C# 建議改用 record 型別(C# 9+)或具名 Tuple,獲得同等簡潔且型別安全的體驗。