前言
C#(C-Sharp)是一種由微軟(Microsoft)開發的 現代化、強型別(Strongly Typed)、物件導向(OOP) 的程式語言。它廣泛應用於 桌面應用程式、Web 開發、遊戲開發(Unity)、等多種領域。
本教學系列希望帶領你以最少的天數,從零開始精通 C#,從 基礎語法 到 進階主題,以極快的速度掌握 C# 核心技能。
希望讀者有心想學的話能夠讀到最後,因為編排上是有目的性的,有些觀念統一放到一起解惑會更好。另外鼓勵讀者能夠實際實作看看,程式碼都是可直接運行的。從輸出Hello World開始
程式碼運行環境
現在,你可以參考官方的安裝手冊安裝程式碼編輯與運行環境,你當然可以打開網路上的C#編譯器,直接開始學習。
C#線上編譯器,你可以跟我一樣使用以下的網站:

那我們就開始吧!
System.Console.WriteLine("Hello World");
System.Console.WriteLine()
會將訊息列印至輸出主控台。- 請注意,若是
Console.WriteLine()
這行語法不小心將大寫部分改成小寫,你的程式碼將會出現錯誤。 - 若你將
Hello World
改以單引號包裹,你的程式碼將會出現錯誤。 - 請記得在在命令結尾使用分號。
System.
要記得添加,不然程式碼會出錯。
註解
// 下面這行會輸出 Hello World
System.Console.WriteLine("Hello World");
- 編譯器會忽略註解的部分,而你則是能透過註解幫助你更好理解程式碼在做甚麼事情。
- 多行註解的話,以
/* */
包裹要註解的內容。
Console.Write() 與 Console.WriteLine()
Console.WriteLine()
會將訊息列印至輸出主控台。並且新增一個換行字元,所以下一次的輸出會在下一行。
System.Console.WriteLine("Hello World!");
System.Console.WriteLine("Hello World!");
/* 輸出
Hello World!
Hello World!
*/
而Console.Write()
則會將訊息印至同一行。
System.Console.Write("Hello World!");
System.Console.Write(" ");
System.Console.Write("Hello World!");
/* 輸出
Hello World! Hello World!
*/
基本資料型態
在 C# 中,變數是用來存放程式運行時會變動的資料,而不同的資料類型適用於不同的數值或文字。C# 提供了多種基本資料型態:
int
、long
、float
、double
、decimal
bool
、char
、string
int age = 20; // 整數
float height = 170.5f; // float (在數字後面加上 'f' 或 'F' )
double weight = 65.3; // double
bool isStudent = true; // 布林值
char gender = 'M'; // 字元,一次只能放置單一字元
string name = "John"; // 字串
System.Console.WriteLine($"Name: {name}, Age: {age}");
System.Console.WriteLine($"Height: {height}, Weight: {weight}");
System.Console.WriteLine($"Is Student: {isStudent}, Gender: {gender}");
System.Console.Write(2.39836m); // decimal (精確度最高,在數字後面加上 'm' 或 'M' )
/* 輸出
Name: John, Age: 20
Height: 170.5, Weight: 65.3
Is Student: True, Gender: M
2.39836
*/
- 上面我們透過先宣告資料型態,接著再為其命名,所以像是 age 、name等,諸如此類的我們都稱其為變數。
- 變數名稱不能以數字開頭命名、變數名稱中也不應包含特殊符號如
#
,變數名稱也不能包含空白鍵。 - 變數名稱不得為”關鍵字”,像是使用
int
當作變數名稱。 - 變數的命名有一種撰寫樣式,它會在第一個單字開頭使用小寫字母,並在每個後續單字的開頭都使用大寫字母,像是
int myDayMoney;
- 為避免出現未指派的區域變數,建議您在宣告變數之後儘快設定此值。
$"文字 {變數}"
這種寫法能直覺地將變數值插入字串,請讀者記住。float
與double
同為浮點數型態,但精度不同,float
精度較低且記憶體佔用量較小;double
提供更高的精度。
引含型別變數
隱含型別區域變數的建立會使用 var 關鍵字,後接變數初始化。
var message = "Hello world!";
var
關鍵字會告訴編譯器根據變數所初始化的值來推斷變數的資料類型。
常數
如果某個值在程式執行期間不會改變,可以使用 const
關鍵字宣告常數。
const double Pi = 3.14159f;
特殊字元的輸出
請考慮以下程式碼:
System.Console.Write("Hello\nWorld!");
/* 輸出
Hello
World!
*/
- 注意,程式碼中,雙引號的內容包含了
\n
,其代表特殊字元,以本例子而言,"\n"
代表新增一行,所以你可以發現我們輸出有兩行。
請再考慮以下程式碼:
System.Console.Write("Hello\tWorld!");
/* 輸出
Hello World!
*/
"\t"
相當於按下 TAB 鍵所產生的空間。
好,最後我們再考慮以下程式碼:
System.Console.WriteLine("Hello\"World\"");
System.Console.WriteLine("Hello\\World");
/* 輸出
Hello"World"
Hello\World
*/
- 若要輸出一些特殊符號,我們可以在特殊符號前添加
\
,程式才不會出錯。
建立逐字字串
逐字字串,它會針對你寫的內容一字不漏地完全映出來,請參考以下程式碼:
System.Console.WriteLine(@"Hello, How
are you~~ ");
/*輸出
Hello, How
are you~~
*/
字串串連
字串串連是只將兩個或多個 string
值合併到新 string
值
所以我們可以使用 +
將字串連接到列一個字串結尾,以下示範:
string firstName = "Michael";
System.Console.WriteLine("Hello " + firstName);
/* 輸出
Hello Michael
*/
另外,我們也可以使用$"文字 {變數}" 讓字串語法更簡潔、更易讀。
string firstName = "Michael";
System.Console.WriteLine($"Hello {firstName}!");
/* 輸出
Hello Michael!
*/
基本運算子
- 數學運算子:
+
、-
、*
、/
、%
- 指派運算子:
=
、+=
、=
、=
、/=
- 比較運算子:
==
、!=
、>
、<
、>=
、<=
- 邏輯運算子:
&&
、||
、!
範例:
int a = 10, b = 3;
// 加法
int sum = a + b; // 10 + 3 = 13
System.Console.WriteLine($"{a} + {b} = {sum}");
// 減法
int difference = a - b; // 10 - 3 = 7
System.Console.WriteLine($"{a} - {b} = {difference}");
// 乘法
int product = a * b; // 10 * 3 = 30
System.Console.WriteLine($"{a} * {b} = {product}");
// 除法 (注意整數除法)
int quotient = a / b; // 10 / 3 = 3 (整數除法,無小數)
System.Console.WriteLine($"{a} / {b} = {quotient}");
// 餘數
int remainder = a % b; // 10 % 3 = 1
System.Console.WriteLine($"{a} % {b} = {remainder}");
//四則運算
System.Console.WriteLine(a + a * b / 5);
/* 輸出
10 + 3 = 13
10 - 3 = 7
10 * 3 = 30
10 / 3 = 3
10 % 3 = 1
16
*/
範例2:
int x = 5;
// 加法指派
x += 3; // 等於 x = x + 3;
System.Console.WriteLine($"x += 3 -> x = {x}");
// 減法指派
x -= 2; // 等於 x = x - 2;
System.Console.WriteLine($"x -= 2 -> x = {x}");
// 乘法指派
x *= 4; // 等於 x = x * 4;
System.Console.WriteLine($"x *= 4 -> x = {x}");
// 除法指派
x /= 2; // 等於 x = x / 2;
System.Console.WriteLine($"x /= 2 -> x = {x}");
/* 輸出
x += 3 -> x = 8
x -= 2 -> x = 6
x *= 4 -> x = 24
x /= 2 -> x = 12
*/
範例3:
int a = 10, b = 20;
// 相等
System.Console.WriteLine($"{a} == {b} -> {a == b}");
// 不相等
System.Console.WriteLine($"{a} != {b} -> {a != b}");
// 大於
System.Console.WriteLine($"{a} > {b} -> {a > b}");
// 小於
System.Console.WriteLine($"{a} < {b} -> {a < b}");
// 大於等於
System.Console.WriteLine($"{a} >= {b} -> {a >= b}");
// 小於等於
System.Console.WriteLine($"{a} <= {b} -> {a <= b}");
範例4:
bool condition1 = true;
bool condition2 = false;
// AND 邏輯
System.Console.WriteLine($"{condition1} && {condition2} -> {condition1 && condition2}");
// OR 邏輯
System.Console.WriteLine($"{condition1} || {condition2} -> {condition1 || condition2}");
// NOT 邏輯
System.Console.WriteLine($"!{condition1} -> {!condition1}");
隱式轉換
如果你嘗試使用 +
符號用在兩種不同的資料型態上,例如:string
與 int
,會發生什麼事?
string Name = "Bob";
int number = 7;
System.Console.WriteLine(Name + " have " + number + 1 + " billion");
/* 輸出
Bob have 71 billion
*/
- 你可以發現,編譯器會將所有內容視為字串,並將它們全都串連在一起,也就是說,
int
變數隱式地暫時轉換為string
。
那我們怎麼讓輸出變為Bob have 8 billion
呢?直接加個括號即可,說明先執行加法動作再執行後續動作。
string Name = "Bob";
int number = 7;
System.Console.WriteLine(Name + " have " + (number + 1) + " billion");
/* 輸出
Bob have 8 billion
*/
顯式轉換
char ch = 'A';
int number = 7;
int a = (int)ch + number; //顯式轉換
System.Console.WriteLine(a);
/* 輸出
72
*/
- A的ASCII碼為65
- 以本例子來說,就算不使用顯式轉換,答案也會正確,因為
ch
會隱式轉換成int
另外,請注意,以下的程式碼都不正確:
int a = 7 / 5.0f;
int b = 7.0f / 5;
int c = 7.0f / 5.0f;
float d = 7 / 5;
System.Console.WriteLine(d);
/* 輸出不正確的結果
1
*/
更安全的轉換
TryParse()
方法
用於字串轉換,若轉換失敗返回 false
(布林值),不會拋出異常。
string str = "123";
int i;
bool success = int.TryParse(str, out i); // 安全轉換
out
是關鍵字一定要加,i就是轉換成功存放值的地方。
as
運算子
用於參考型別的轉換,若轉換失敗會返回 null,不會拋出異常。
object obj = "Hello";
string str = obj as string; // 轉換成功
int? num = obj as int?; // 轉換失敗,返回 null
安全性:較高,但僅適用於參考型別和可為空的型別(如 int?
、long?
、bool?
等)。
- 參考型別和可為空的型別: (這可以暫且忽略沒關係)。
Convert
類別
提供靜態方法進行轉換,若轉換失敗會拋出異常
string str = "123";
int i = System.Convert.ToInt32(str); // 轉換成功
i += 1;
System.Console.WriteLine(i); // 124
遞增與遞減運算子
int x = 5;
System.Console.WriteLine($"x = {x}");
// 前置遞增
System.Console.WriteLine($"++x = {++x}"); // (值先加1,再輸出)
// 後置遞增
System.Console.WriteLine($"x++ = {x++}"); // (輸出值後,再加1)
System.Console.WriteLine($"x = {x}");
// 前置遞減
System.Console.WriteLine($"--x = {--x}"); // (值先減1,再輸出)
// 後置遞減
System.Console.WriteLine($"x-- = {x--}"); // (輸出值後,再減1)
System.Console.WriteLine($"x = {x}");
// 與表達式結合
int y = 10;
int result = ++x + y--; // ++x 為前置遞增,y-- 為後置遞減
System.Console.WriteLine($"result = ++x + y-- -> result = {result}");
System.Console.WriteLine($"x = {x}, y = {y}");
/* 輸出
x = 5
++x = 6
x++ = 6
x = 7
--x = 6
x-- = 6
x = 5
result = ++x + y-- -> result = 16
x = 6, y = 9
*/
取得用戶輸入
使用Console.ReadLine()
讀取用戶輸入,請記住,用戶輸入的都是字串,而字串並不能執行一些數值的運算,所以我們使用int.Parse()
將輸入字串轉換為整數。
// 提示用戶輸入
System.Console.Write("Your name: ");
string name = System.Console.ReadLine();
System.Console.Write("Enter a number: ");
int num = int.Parse(System.Console.ReadLine());
// 顯示初始值
System.Console.WriteLine($"{num}");
// 前置遞增
System.Console.WriteLine($"(++num): {++num}");
// 後置遞增
System.Console.WriteLine($"(num++): {num++}");
System.Console.WriteLine($"{num}");
// 前置遞減
System.Console.WriteLine($"(--num): {--num}");
// 後置遞減
System.Console.WriteLine($"(num--): {num--}");
System.Console.WriteLine($"{num}");
/* 輸出
Your name: Bob
Enter a number: 5
5
(++num): 6
(num++): 6
7
(--num): 6
(num--): 6
5
*/
C# 方法與類別的基本概念
到目前為止,我們一直在使用Console.Write()
、Console.WriteLine()
、剛還提到Console.ReadLine()
、甚至是int.Parse()
,這些看似能執行特定功能的語法究竟是甚麼呢?
在 C# 中,像 Console.Write()
、Console.WriteLine()
、Console.ReadLine()
、int.Parse()
這些語法都是方法(Methods),方法是一段可以重複執行的程式碼,用於完成特定功能。它們的功能、來源和用途如下解釋:
方法的定義
- 方法是一組具有特定功能的程式碼,可以被呼叫來執行。
- 方法可以有輸入參數(Input Parameters)和返回值(Return Value)。
來源
- 這些方法來自 .NET 的類別庫,屬於不同的類別(Class)。
- 一些核心的類別庫(如
Console
、Math
等)是內建的,無需手動引用即可使用。
類別
- 類別是什麼?
- 類別是一個用來定義物件屬性(Attributes)和行為(Behaviors)的模板。
- 它描述了物件的結構和行為,而物件則是類別的實例。
- 物件與類別的關係
- 類別是抽象的設計,物件是具體的實現。
- 例如:類別 = 藍圖物件 = 依照藍圖建造的房子
- 類別中的組成部分
- 屬性(Attributes):描述物件的資料,例如名稱、年齡。
- 方法(Methods):描述物件的功能或行為,例如計算、顯示資訊。
而讀者要特別注意,如果語法為:類別名稱.方法名稱(參數)
,我們稱其為靜態方法(Static Method),而與其相對的是實例方法,方法的呼叫需要仰賴物件,也就是說,建立物件後才能使用的方法稱為 “實例方法” 關於這個我們以後才會提到。
靜態方法:
System.Console.WriteLine("Static Method");
好,你可能又會好奇為甚麼要添加System.
,目前讀者只需了解大概的原理:
- C# 使用 命名空間 來組織和區分不同的類別。例如,
Console
類別位於System
命名空間中,完整名稱是System.Console
。 - 如果不加入
System.
,編譯器無法自動找到Console
類別,因為它不知道你要引用的是哪個命名空間中的類別。 - 如果你的開發環境是較高版本的話,你有可能不需要添加
System.
,讀者只要知道,如果出現錯誤的話記得添加System.
即可,亦或是按照線上編譯器一開始給你的程式碼片段進行編寫,如下圖。
