Day 3 的練習中,我們曾經寫過:
var price = 120;
var quantity = 5;
var total = price * quantity;
Console.WriteLine(total);
當時我們先直接使用 var,但還沒有正式說明:
var 是什麼?price、quantity 是什麼?今天就來正式認識 C# 的:
Variable(變數)與 Type System(型別系統)。
今天的核心:理解資料如何被儲存在 Variable 中、每個 Variable 為什麼都有 Type,以及不同 Type 之間如何進行轉換。
var 與 Type InferenceParse() / TryParse()
Variable(變數)可以先理解成:
程式執行時,用來儲存資料的名稱。
例如:
int quantity = 10;
可以拆成:
int quantity = 10;
↓ ↓ ↓
Type Variable Name Value
其中:
int:資料型別quantity:Variable Name10:Variable 儲存的 Value例如一筆訂單可能需要:
string productName = "TXF";
decimal price = 21500.5m;
int quantity = 2;
bool isFilled = false;
不同種類的資料,會使用不同的 Type。
"TXF"
↓
文字
21500.5
↓
價格
2
↓
數量
false
↓
狀態
所以 Variable 不只是「存資料」,C# 還需要知道:
這筆資料是什麼 Type。
先看:
int quantity = 10;
這一行其實同時完成了:
建立 Variable
+
設定初始值
如果拆開寫:
int quantity;
quantity = 10;
第一行:
int quantity;
稱為:
Declaration(宣告)
代表建立一個:
名稱:quantity
Type:int
的 Variable。
第二行:
quantity = 10;
則是:
Assignment(賦值)
把 10 指派給 quantity。
如果宣告 Variable 時直接設定初始值:
int quantity = 10;
通常稱為:
Initialization(初始化)
也就是:
Variable 建立時的第一次賦值。
int quantity = 10;
quantity = 20;
Console.WriteLine(quantity);
結果:
20
因為後面的:
quantity = 20;
會把原本的 10 改成 20。
重新賦值時不需要再次寫:
int
因為 quantity 已經宣告過。
正確:
quantity = 20;
C# 提供許多內建型別。
先認識幾個開發中常看到的:
| Type | 用途 | 範例 |
|---|---|---|
int |
整數 | 10 |
long |
較大範圍的整數 | 10000000000L |
float |
單精度浮點數 | 10.5f |
double |
一般浮點數 | 10.5 |
decimal |
精確十進位數值 | 10.5m |
bool |
布林值 | true |
char |
單一字元 | 'A' |
string |
字串 | "Hello" |
我們可以先分成三組來理解:
數值
↓
int / long / float / double / decimal
狀態
↓
bool
文字
↓
char / string
intint 用來表示一般整數。
int quantity = 10;
int orderCount = 100;
像:
商品數量
筆數
次數
年齡
這類沒有小數的資料,通常會先考慮 int。
long如果整數可能超過 int 可以表示的範圍,可以使用:
long orderNumber = 10000000000L;
這裡的:
L
表示這個整數 Literal 是 long。
一般情況先使用 int 即可,需要更大的整數範圍時再考慮 long。
float、double、decimal如果資料包含小數,常見的有:
float rate1 = 1.5f;
double rate2 = 1.5;
decimal price = 100.5m;
其中:
f
↓
float
m
↓
decimal
doubledouble 是一般浮點數計算常見的型別。
例如:
double temperature = 26.5;
decimaldecimal 適合需要精確十進位表示的數值,例如:
價格
金額
財務計算
例如:
decimal price = 21500.5m;
因此涉及金額時,通常會看到:
decimal price = 100.5m;
而不是單純使用:
double price = 100.5;
boolbool 用來表示只有兩種狀態的資料:
true
false
例如:
bool isFilled = true;
bool isCancelled = false;
未來寫條件判斷時會大量使用 bool。
char 與 stringcharchar 表示:
單一字元
使用單引號:
char side = 'B';
stringstring 表示:
一段文字
使用雙引號:
string productName = "TXF";
簡單區分:
'A'
↓
char
"ABC"
↓
string
在 C# 中,每個 Variable 都有明確的 Type。
例如:
int quantity = 10;
string productName = "TXF";
C# 知道:
quantity
↓
int
productName
↓
string
因此不能把不相容的資料任意指派進去。
例如:
int quantity = 10;
quantity = "Ten";
這段程式無法通過編譯。
因為:
quantity
↓
int
"Ten"
↓
string
型別不相容。
假設:
int quantity = 10;
Compiler 知道 quantity 是整數,所以可以做:
int total = quantity * 2;
但如果:
string quantity = "10";
這時 quantity 是文字。
即使內容看起來像:
10
它仍然是:
string
這就是 Type System 的重要性。
資料看起來一樣,不代表它們的 Type 一樣。
C# 可以在編譯階段檢查許多不合法的型別操作,讓部分問題在程式真正執行前就被發現。
var 是什麼?除了明確寫出 Type:
int quantity = 10;
C# 也可以寫:
var quantity = 10;
var 代表讓 Compiler 根據右側的資料進行:
Type Inference(型別推斷)
例如:
var quantity = 10;
var productName = "TXF";
var isFilled = false;
Compiler 會推斷:
quantity
↓
int
productName
↓
string
isFilled
↓
bool
所以:
var quantity = 10;
並不是代表 quantity 沒有 Type。
Compiler 已經知道:
quantity
↓
int
因此後面不能改成:
quantity = "Ten";
會發生 Compile Error。
var 與 JavaScript 不一樣如果本來熟悉 JavaScript,這裡很容易混淆。
JavaScript:
let value = 10;
value = "Hello";
同一個 Variable 可以在不同時間存放不同 Type 的值。
但 C#:
var value = 10;
value = "Hello";
不行。
因為:
var value = 10;
在編譯時就已經推斷成:
int
所以最重要的一句:
C# 的
var是型別推斷,不是動態型別。
var?下面兩種寫法都合法:
int quantity = 10;
以及:
var quantity = 10;
如果右側很容易看出 Type:
var quantity = 10;
var productName = "TXF";
var isFilled = false;
使用 var 可以減少重複資訊。
但如果使用 var 反而讓程式碼難以理解,就不一定比較好。
可以先記住一個簡單原則:
使用
var不應該降低程式碼的可讀性。
實際開發中,資料不一定一開始就是我們需要的 Type。
例如使用者輸入:
"10"
看起來是數字。
但從 Console、API、檔案或表單取得的資料,有時可能會是:
string
如果要進行數學計算,就可能需要把:
"10"
string
轉成:
10
int
這就是:
Type Conversion(型別轉換)
常見方式有:
Implicit Conversion
Explicit Conversion / Casting
Parse()
TryParse()
有些型別可以安全地轉換成另一個型別,Compiler 可以自動處理。
例如:
int quantity = 100;
long totalQuantity = quantity;
這裡發生:
int
↓
long
不需要寫額外的轉型語法。
這稱為:
Implicit Conversion(隱含轉換)
可以先理解成:
Compiler 確認這個轉換可以安全完成,所以自動幫我們轉。
有些轉換可能造成資料遺失,因此需要明確告訴 Compiler:
我要進行這個轉換。
例如:
double price = 100.8;
int result = (int)price;
Console.WriteLine(result);
結果:
100
其中:
(int)
就是:
Casting(轉型)
流程:
double 100.8
↓
(int)
↓
int 100
要注意:
將浮點數轉成
int時,小數部分會被截掉,不會自動四捨五入。
例如:
double number = 99.9;
int result = (int)number;
Console.WriteLine(result);
結果仍然是:
99
Parse():把文字解析成數字實際開發很常遇到:
string quantityText = "10";
雖然內容看起來是數字:
10
但它的 Type 仍然是:
string
如果想轉成 int:
int quantity = int.Parse(quantityText);
流程:
"10"
string
↓
int.Parse()
↓
10
int
完整範例:
string quantityText = "10";
int quantity = int.Parse(quantityText);
Console.WriteLine(quantity);
結果:
10
如果資料是:
string quantityText = "ABC";
再執行:
int quantity = int.Parse(quantityText);
因為:
"ABC"
無法解析成整數,所以程式執行時會發生錯誤並拋出 Exception。
Exception Handling 會在後面的章節正式介紹。
目前先記住:
Parse()預期輸入資料必須是正確格式。
TryParse():不確定資料正不正確時如果資料來自使用者輸入,我們不能保證格式一定正確。
例如:
string quantityText = "10";
可以使用 TryParse() 嘗試轉換:
bool success = int.TryParse(
quantityText,
out int quantity
);
其中:
success:表示轉換是否成功out int quantity:接收轉換後的整數結果如果轉換成功:
success → true
quantity → 10
如果轉換失敗:
success → false
ifstring quantityText = "10";
if (int.TryParse(quantityText, out int quantity))
{
Console.WriteLine($"轉換成功:{quantity}");
}
else
{
Console.WriteLine("請輸入正確的整數");
}
當內容是:
"10"
結果:
轉換成功:10
如果改成:
"ABC"
結果:
請輸入正確的整數
所以可以簡單記成:
TryParse()用bool表示轉換是否成功,並透過out取得轉換後的結果。
當輸入資料格式不確定時,TryParse() 通常會比直接使用 Parse() 更適合。
Parse() 與 TryParse() 的差別可以整理成:
| 方法 | 成功 | 格式錯誤 |
|---|---|---|
Parse() |
回傳轉換後的結果 | 拋出 Exception |
TryParse() |
回傳 true,並取得結果 |
回傳 false |
如果資料來源是:
使用者輸入
API
檔案
外部系統
而資料格式不一定可靠,通常可以優先考慮:
TryParse()
如果程式邏輯可以確定資料一定是合法格式,才可能直接使用:
Parse()
今天我們認識了 C# 的 Variable 與 Type System。
在 C# 中,每個 Variable 都有明確的 Type。Type 會決定這個 Variable 可以儲存什麼資料,以及可以進行哪些操作。
int quantity = 10;
可以拆成:
int quantity 10
↓ ↓ ↓
Type Name Value
也就是:
Variable 用來儲存資料,而 Type 用來描述這筆資料的種類。
int
→ 整數
long
→ 較大範圍的整數
double
→ 一般浮點數
decimal
→ 精確十進位數值
bool
→ true / false
char
→ 單一字元
string
→ 字串
不同種類的資料,會使用不同的 Type。
varvar quantity = 10;
Compiler 會根據右側的值推斷:
quantity
↓
int
所以:
var是 Type Inference(型別推斷),不是沒有 Type,也不是動態型別。
Variable 的 Type 一旦推斷完成,就不會任意改成其他 Type。
不同 Type 之間有時需要進行轉換。
Implicit Conversion
↓
Compiler 自動完成安全的型別轉換
Casting
↓
明確指定要轉成另一個 Type
Parse()
↓
把文字解析成指定 Type
格式錯誤時可能拋出 Exception
TryParse()
↓
嘗試解析資料
使用 bool 表示成功或失敗
可以把 Day 4 收斂成四件事:
Variable 用來儲存資料
↓
每個 Variable 都有 Type
↓
var 仍然會推斷出明確的 Type
↓
不同 Type 之間有時需要進行 Conversion
理解 Variable、Type 與 Conversion 的關係,是後續學習運算、條件判斷、Method 與物件的重要基礎。