從 C/C++ 轉向 C# 的開發者,最容易踩到的坑之一就是**型別轉換規則的根本差異**。C/C++ 中 bool、指標、整數、浮點數可自由隱含轉換 (如 if (ptr)、if (x)),C# 為了**型別安全** 嚴格禁止這些隱含轉換,強制開發者撰寫明確的比較運算式。本文詳細解析 C# 的 bool 型別限制、數值型別隱含/顯式轉換規則、byte 運算陷阱、char 字元分類方法,並提供實務編碼建議。
int x = 123;
if (x) { /* 非零即 true */ } // 合法
if (!x) { /* 零即 false */ } // 合法
bool b = x; // 合法:非零→true, 零→false
int y = b; // 合法:true→1, false→0
int x = 123;
// if (x) { } // ❌ 編譯錯誤 CS0029: 無法將 'int' 隱含轉換為 'bool'
// bool b = x; // ❌ 編譯錯誤 CS0029
// int y = b; // ❌ 編譯錯誤 CS0029
// ✅ 正確寫法:明確比較
if (x != 0) { } // 明確檢查非零
if (x == 0) { } // 明確檢查零
bool b = (x != 0); // 明確轉換
int y = b ? 1 : 0; // 明確轉換 (三元運算子)
C# 採用**強型別、明確意圖** 原則:
bool只能代表邏輯真假,絕不隱含對應數值。這消除了大量「非零即真」導致的邏輯錯誤 (如函數回傳 -1 表錯誤卻被當 true)、指標判空語義混淆、位元運算誤用為邏輯運算等經典 Bug。
C# 定義了**嚴格的隱含數值轉換表**,僅允許**資訊不遺失**的擴寬轉換:
sbyte → short → int → long
↘ ↘ ↘
(也可轉向 float/double/decimal)
byte → ushort → uint → ulong
↘ ↘ ↘
(也可轉向 float/double/decimal)
float → double
(無 float→decimal 隱含轉換,因 decimal 精度更高但範圍較小)
char → ushort → uint → ulong → float → double → decimal
(char 不隱含轉換為有號整數,因 char 為無號 0~65535)
| 來源型別 | 可隱含轉換的目標型別 |
|---|---|
sbyte | short, int, long, float, double, decimal |
byte | short, ushort, int, uint, long, ulong, float, double, decimal |
short | int, long, float, double, decimal |
ushort | int, uint, long, ulong, float, double, decimal |
int | long, float, double, decimal |
uint | long, ulong, float, double, decimal |
long | float, double, decimal |
ulong | float, double, decimal |
float | double |
char | ushort, int, uint, long, ulong, float, double, decimal |
long → int (可能溢位)double → float (精度遺失)double/float → decimal (需顯式 (decimal)d)decimal → double/float (需顯式)有號 ↔ 無號 互轉 (如 int → uint, long → ulong)浮點數 → 整數 (截斷小數部)byte x = 200, y = 100;
byte z = x + y; // ❌ 編譯錯誤 CS0266: 無法將 'int' 隱含轉換為 'byte'
byte、sbyte、short、ushort 參與算術運算時,**自動提升為 int** 進行運算 (CLI 標準)。int,無法隱含指派回 byte。// 1. 顯式 Cast (若確定不溢位)
byte z = (byte)(x + y); // 結果 44 (300 % 256)
// 2. 使用 checked 區塊 (溢位拋出 OverflowException)
byte z;
checked { z = (byte)(x + y); } // 拋出例外
// 3. 改用 int/long 運算,最後再 Cast
int sum = x + y;
byte z = (byte)sum;
System.Char 提供豐富的 Unicode 字元分類靜態方法,回傳 bool,適合輸入驗證:
| 方法 | 說明 | 範例 |
|---|---|---|
IsLetter(c) | 是否字母 (Unicode Letter) | 'A', '中', 'あ' → true |
IsDigit(c) | 是否十進位數字 (0-9) | '5' → true |
IsLetterOrDigit(c) | 字母或數字 | |
IsLower(c) | 是否小寫字母 | 'a' → true, 'A' → false |
IsUpper(c) | 是否大寫字母 | |
IsWhiteSpace(c) | 是否空白字元 (空格、Tab、換行) | |
IsPunctuation(c) | 是否標點符號 | |
IsSymbol(c) | 是否符號 (數學、貨幣等) | |
IsControl(c) | 是否控制字元 (非列印) | |
IsNumber(c) | 是否數字 (含分數、羅馬數字等) | |
GetUnicodeCategory(c) | 取得詳細 Unicode 類別 |
using System;
class CharDemo
{
static void Main()
{
Console.Write("請輸入一個字元: ");
char c = (char)Console.Read(); // 讀取單一字元
if (Char.IsLetter(c))
{
Console.WriteLine("輸入為字母。");
if (Char.IsLower(c))
Console.WriteLine("為小寫字母。");
else
Console.WriteLine("為大寫字母。");
}
else if (Char.IsDigit(c))
{
Console.WriteLine("輸入為數字。");
}
else if (Char.IsWhiteSpace(c))
{
Console.WriteLine("輸入為空白字元。");
}
else
{
Console.WriteLine("輸入為其他符號/控制字元。");
}
}
}
if (x != 0)、if (obj != null)、if (list.Count > 0),拒絕「非零即真」慣用語。var 但保留型別意識:var sum = x + y; 推斷為 int,指派給 byte 仍需 Cast。Convert.ToXxx 或 TryParse:處理溢位、格式錯誤比 Cast 更安全。checked 區塊或專案設定「檢查算術溢位」:Debug 建議開啟,Release 評估效能影響。Char 靜態方法:正確支援 Unicode,避免手寫 c >= 'a' && c <= 'z' 只支援 ASCII 的錯誤。bool 與數值互轉:需轉換時用三元運算子 b ? 1 : 0 或 Convert.ToInt32(b)。C# 的型別系統以**安全性優先**為核心設計原則:bool 嚴格隔離邏輯與數值、隱含轉換僅允許資訊不遺失的擴寬轉換、算術運算自動提升至 int 避免無聲溢位、Char 方法提供完整 Unicode 支援。理解並遵循這些規則,能在編譯期攔截 90% 以上的型別相關 Bug,寫出更健壯、可維護的程式碼。從 C/C++ 轉型的開發者,請務必建立「明確比較、顯式轉換、編譯期檢查」的肌肉記憶。