C# 是強型別語言,每個變數、運算式、方法參數/回傳值都有固定型別。理解型別分類、記憶體模型、預設值、大小、轉換規則,是寫出高效、正確程式碼的基礎。
| 分類 | 型別範例 | 基底類別 | 記憶體 | 指派 | Null |
|---|---|---|---|---|---|
| 實值型別 | int, double, bool, struct, enum, DateTime | System.ValueType | 堆疊/內嵌 | 複製值 | 不可 (除非 T?) |
| 參考型別 | class, string, array, delegate, interface | System.Object | 堆積 | 複製參考 | 可 |
| 指標型別 | int*, void*, Span<T>* | — | 堆疊 | 複製位址 | 可 |
| 型別 | 別名 | 大小 | 範圍 / 精度 | 預設值 |
|---|---|---|---|---|
| System.SByte | sbyte | 1 byte | -128 ~ 127 | 0 |
| System.Byte | byte | 1 byte | 0 ~ 255 | 0 |
| System.Int16 | short | 2 bytes | -32,768 ~ 32,767 | 0 |
| System.UInt16 | ushort | 2 bytes | 0 ~ 65,535 | 0 |
| System.Int32 | int | 4 bytes | -2,147,483,648 ~ 2,147,483,647 | 0 |
| System.UInt32 | uint | 4 bytes | 0 ~ 4,294,967,295 | 0 |
| System.Int64 | long | 8 bytes | -9.22e18 ~ 9.22e18 | 0L |
| System.UInt64 | ulong | 8 bytes | 0 ~ 1.84e19 | 0UL |
| System.Single | float | 4 bytes | ±1.5e-45 ~ ±3.4e38, ~7 位數 | 0.0F |
| System.Double | double | 8 bytes | ±5.0e-324 ~ ±1.7e308, ~15 位數 | 0.0D |
| System.Decimal | decimal | 16 bytes | ±1.0e-28 ~ ±7.9e28, 28-29 位數 | 0.0M |
| System.Boolean | bool | 1 byte | true/false | false |
| System.Char | char | 2 bytes | U+0000 ~ U+FFFF | '\0' |
| System.DateTime | — | 8 bytes | 0001-01-01 ~ 9999-12-31 | DateTime.MinValue |
| System.Guid | — | 16 bytes | 128-bit 唯一識別碼 | Guid.Empty |
sizeof 運算子// 編譯期常數 (內建型別)
int size = sizeof(int); // 4
int size2 = sizeof(DateTime); // 8
// 結構體需 unsafe context (除非無參考欄位)
unsafe { int size3 = sizeof(MyStruct); }
object:所有型別的終極基底object o = 42; // 裝箱
object o2 = "hello";
object o3 = new int[] {1,2,3};
// 所有型別 (含實值型別裝箱後) 皆可指派給 object
dynamic:延遲繫結dynamic d = "hello";
Console.WriteLine(d.Length); // 執行期解析,失敗拋 RuntimeBinderException
d = 42;
Console.WriteLine(d * 2); // 執行期解析
// 編譯期不檢查成員存取,類似動態語言
string:不可變字串string s = "hello";
string s2 = @"C:\Path"; // 逐字字串
string s3 = $"{DateTime.Now}"; // 插值字串
// string 為參考型別,但行為類似值型別 (不可變、== 比較內容)
int[], string[,] 隱含繼承 System.ArrayAction, Func<T, TResult>, 自訂委派IEnumerable<T>, IDisposable 等僅在 unsafe 內容使用,直接操作記憶體位址:
unsafe {
int i = 42;
int* p = &i; // 取得位址
Console.WriteLine(*p); // 解參考
int[] arr = {1,2,3};
fixed (int* ptr = arr) { // 固定陣列不被 GC 移動
for (int j = 0; j < 3; j++) Console.WriteLine(ptr[j]);
}
}
用途:高效能互通、圖形處理、網路封包解析、與 C/C++ 互操作。現代替代方案:Span<T>, Memory<T>, Unsafe 類別。
定義所有 .NET 語言共用的型別規範:實值/參考型別、繼承規則、成員類型、存取修飾詞。
CTS 子集,確保跨語言互操作:不使用無號整數、區分大小寫成員名、無指標等。
編譯期 + 執行期防止型別錯誤:存取不存在成員、錯誤轉換、陣列越界皆會被攔截。
| 情境 | 實值型別 | 參考型別 |
|---|---|---|
| 欄位/陣列元素 | 全零 (0/false/\0) | null |
| 區域變數 | 需明確初始化 | 需明確初始化 |
default(T) | 全零 | null |
new T() | 呼叫無參數建構子 | 呼叫建構子 |
| 場景 | 推薦型別 | 理由 |
|---|---|---|
| 整數計數/索引 | int | CPU 原生、效能最佳、預設推斷 |
| 大整數/識別碼 | long / Guid | 範圍足夠、唯一性 |
| 金額/財務計算 | decimal | 十進位精確、避免浮點誤差 |
| 科學計算/測量 | double | 範圍大、硬體加速、精度足夠 |
| 單精度/圖形/GPU | float | 記憶體省、頻寬低、SIMD 友善 |
| 布林旗標 | bool | 語意明確 |
| 單一字元 | char | UTF-16 代碼單元 |
| 小型不可變資料 | readonly struct | 堆疊配置、複製語意、無 GC |
| 大型/共享/可變物件 | class / record | 參考語意、身分識別、繼承 |
| 字串文字 | string | 不可變、內建優化 |
// 實值型別包裝
int? nullableInt = null;
bool? flag = null;
DateTime? birthday = null;
// 參考型別 (C# 8+ nullable context)
string? nullableString = null;
List? nullableList = null;
// 底層結構
// public struct Nullable where T : struct {
// public bool HasValue { get; }
// public T Value { get; } // HasValue=false 時擲出
// }
in、ref、或改為 class。<Nullable>enable</Nullable> 讓編譯器協助防禦 NullReferenceException。Span<T>/Memory<T>。string 是實值型別還是參考型別?A: 參考型別 (繼承 object),但行為像值型別:不可變、== 比較內容、預設值 null。
sizeof(bool)?A: bool 在 CLI 規範中大小未指定 (通常 1 byte)。C# 允許 sizeof(bool) 但需 unsafe context。
DateTime 是實值型別嗎?A: 是,struct,8 bytes (ticks 長整數)。
uint/ulong?A: 位元操作、互通原生 API、CLS 合規性不需求時。公開 API 慣用 int/long。