小提示
剛開始開發軟體嗎? 先從 入門 教學開始。 它們會在你寫第一批程式時引入類型。
有其他語言的經驗嗎? C# 內建型別與 Java、C++ 及其他語言的型別對應非常緊密。 略讀 字面上的語法 和 型別推論 部分,了解 C# 專屬細節。
C# 提供了一組內建型別,你可以在任何程式中使用,無需額外引用。 這些類型涵蓋你最常用的資料:數字、真偽值、個別字元和文字。 若想完整地將 C# 關鍵字映射到 .NET 型別,請參見內建型別(C# 參考)。
數值類型
C# 內建整數、浮點數和十進位數的類型。 最常用的類型有 int、 double、 和 decimal:
int population = 67_000_000;
long distance = 384_400_000L;
short temperature = -40;
byte red = 255;
double pi = 3.141592653589793;
float gravity = 9.81f;
decimal price = 19.99m;
每個數字類型都有固定的大小和範圍。
int儲存 32 位元整數(約± 21 億)、long儲存 64 位元整數,而short和byte則儲存較小的值。 完整大小與範圍列表,請參見 積分數值類型 與 浮點數值類型。
double用於一般浮點數運算、float記憶體受限時,以及decimal需要精確小數精確度(例如財務計算)時。 把f後綴附加到float字面上,並把m後綴附加到decimal字面上。 若無後綴,編譯器會將帶有小數點的數字視為double。
無符號類型
每個有符號整數類型都有一個無符號對應類型,該類型僅儲存非負值,其範圍是其正值範圍的兩倍。
uint fileSize = 4_294_967_295;
ulong totalBytes = 18_446_744_073_709_551_615;
ushort port = 443;
當負值不適用於資料時,例如檔案大小或網路埠,你可能會使用無符號類型。 實務上,由於 .NET API 的預設值是有符號型別,許多應用程式即使在僅需正值時也使用 int 或 long。
原生大小整數
nint和 nuint 類型代表整數,其大小與平台的原生指標大小一致:在 32 位元平台上是 32 位元,在 64 位元平台上是 64 位元。
nint bufferSize = 1024;
nuint elementCount = 256;
你不太可能需要 nint ,也 nuint 不太可能在日常程式碼中出現。 它們存在於互操作情境及低階記憶體操作中,當平台指標大小匹配很重要時。 堅持使用 int ,或 long 除非你有特定理由使用原生尺寸的類型。 如需詳細資訊,請參閱 nint 和 nuint。
bool、char 和 string
除了數字之外,C# 還提供了另外三種常用的內建類型:
bool isValid = true;
char grade = 'A';
string greeting = "Hello, world!";
-
bool— 儲存true或false。 在條件、迴圈和邏輯表達式中使用它。 -
char— 儲存一個 Unicode 字元(UTF-16 碼單元),以單引號包覆。 -
string— 儲存一連串字元,並以雙引號包圍。 弦是 不變的。 一旦你建立了字串,就無法更改它的內容。 看似修改字串的操作,實際上會產生新的字串。
字串是 C# 中最常用的類型之一。 關於字串操作的深入介紹,包括插值、原始字串字面量、搜尋、拆分與比較,請參閱 字串 章節。
字面語法
字面值是你直接寫在程式碼中的一個值。 編譯器會根據格式和你提供的後綴,為每個字面值指派一個型別。 C# 支援以下類型的文字:
-
整數字面值 — 十進位(
42)、十六進位(0x2A)、二進位(0b_0010_1010)。 -
浮點數字面值 —
double預設為3.14(),後綴為floatf(3.14f),且decimal使用m(3.14m)。 -
字元字面值 — 單個字元置於單引號
'A'內,包括跳脫序列'\n'。 -
字串字面值 — 正則
"hello"()、逐字(@"C:\path")、原始""" ... """()、插值($"value: {x}")。 -
布林字面值 —
true和false。 -
null文字 — 表示參考型別與可空值型別的值缺失。 -
default字面值 — 產生任何型別的預設值 (詳見default表達式)。
以下章節將詳細介紹最常見的字面形式。
整數字面值
int dec = 42;
int hex = 0x2A;
int bin = 0b_0010_1010;
long big = 1_000_000_000L;
十六進位用 0x 前綴,二進位用 0b 前綴。 附加 L 用於 long 、 U 用於 uint 或 UL 用於 ulong。
數字分隔符可以放在 _ 數字內的任何位置,這樣更容易閱讀。 常見模式包括十進位文字1_000_000_000中的千位分隔符、十六進位0xFF_FF中的位元組或字界限,以及二進位0b_0010_1010中的半位元界限。
浮點數文字
double d = 3.14;
float f = 3.14f;
decimal m = 3.14m;
double scientific = 1.5e6; // 1,500,000
若無後綴,帶有小數點的數值文字為 double。 為 float 附加 f,為 decimal 附加 m。 同時也支援科學記號1.5e6()。
字元與字串字面值
char newline = '\n';
char unicode = '\u0041'; // 'A'
string message = $"Found {dec} items"; // interpolated string
string path = @"C:\Users\docs\file.txt"; // verbatim string
string json = """
{ "name": "Alice", "age": 30 }
"""; // raw string literal
string raw = $"""
Found {dec} items in "{greeting}"
"""; // raw + interpolated
字元文字使用單引號並支援跳脫序列(\n, \t, \u)。 字串文字使用雙引號。
請在字串前加上$ 進行插值。 當字串包含引號、斜線或嵌入的 JSON 或 XML 時,請使用原始字串字面值(以 """為界隔)而非逐字元跳脫。 原始字串文字也會與插值$"""()結合。
舊程式碼使用 @ (逐字串)來避免跳脫處理。 原始字串字面值比較容易讀寫,所以新程式碼會偏好用它們。
default 表達式
此default 表達式產生一個類型的預設值:0 是用於數值型別,false 是用於bool,以及 null 是用於參考型別。
int defaultInt = default; // 0
bool defaultBool = default; // false
string? defaultString = default; // null
// Use default in a conditional:
var limit = (args.Length > 0) ? int.Parse(args[0]) : default(int);
這個default表達式在通用程式碼中最有用,因為你不知道具體的類型,也無法硬編碼像 或 0這樣的特定值null。 當編譯器能從上下文推斷出型別,或default型別不明顯時,寫入default(T)(不加型別參數)。 關於依類型分類的完整預設值清單,請參見 C# 型別的預設值。
隱式型別變數 var
關鍵字指示 var 編譯器從初始化器推斷出本地變數的型別:
var count = 10; // compiler infers int
var name = "C#"; // compiler infers string
var items = new List<int>(); // compiler infers List<int>
// var requires an initializer — the compiler needs a value to infer the type.
// The following line wouldn't compile:
// var unknown;
變數仍然是強型別的;var 不會使它變成動態型別。 編譯器會在編譯時決定型別,並照常強制執行型別安全。 當字體從右側明顯可見時使用 var ,以減少視覺雜訊。 等到程式碼更清楚時再說出類型。 更多資訊請參見 隱式型別的局部變數。
目標類型 new 表達式
當你已經從上下文中知道目標型別,例如變數宣告或方法參數時,你可以省略表達式中的 new 型別名稱:
List<string> names = new() { "Alice", "Bob", "Charlie" };
Dictionary<string, int> scores = new()
{
["Alice"] = 95,
["Bob"] = 87
};
當類型名稱過長或出現在指派的左側時,目標類型 new 可以減少重複。 它適用於編譯器能判斷目標型別的任何地方,包括方法參數和回傳語句。 欲了解更多資訊,請參閱new操作員 — 目標型別。new
dynamic 類型
此 dynamic 型別可繞過編譯時型別檢查。 編譯器在執行時解析 dynamic 變數的操作。
dynamic value = 42;
Console.WriteLine(value.GetType()); // System.Int32
value = "Now I'm a string";
Console.WriteLine(value.GetType()); // System.String
// The compiler doesn't check operations on dynamic at compile time.
// Errors surface at run time instead.
當與 COM API、動態語言或在編譯時型別未知的反射重度情境互動時使用 dynamic 。 大多數應用程式碼避免 dynamic 使用,因為會失去編譯時的安全。 編譯器通常捕捉的錯誤會變成執行時例外。 欲了解更多資訊,請參閱 動態類型。