編碼 · 程式語言
C# 入門教學
簡答
C# 是 Microsoft 推出的靜態型別物件導向語言,執行於 .NET 之上,.NET 是可在 Windows、macOS 與 Linux 上使用的免費跨平台執行環境。安裝 .NET SDK 後執行 dotnet new console,再執行 dotnet run 就會印出「Hello, World!」。核心概念包括類別與 record、List<T> 和 Dictionary<K, V> 等泛型集合、LINQ 查詢、async/await、模式比對與例外處理。
C# 是什麼,用來做什麼
C#(讀作「C sharp」)由 Microsoft 內部以 Anders Hejlsberg 為首的團隊設計,於 2002 年首次發布。它由 Ecma 標準化(ECMA-334),並與 .NET 一同以開放方式開發。C# 用於網頁 API 與網站(ASP.NET Core)、Windows 桌面應用程式、跨平台行動與桌面應用程式(.NET MAUI)、雲端服務與遊戲:Unity 引擎就使用 C# 撰寫遊戲腳本。它的語法屬於 C 家族,因此 Java、C++ 與 JavaScript 開發者會覺得很熟悉。
安裝 .NET 並執行 Hello, world
從 dot.net 下載 .NET SDK,並用 dotnet --version 確認。建立並執行主控台專案:
dotnet new console -o HelloApp
cd HelloApp
dotnet run
# Hello, World!範本會建立 Program.cs,它使用最上層陳述式(top-level statements),因此小程式不需要類別或 Main 方法:
Console.WriteLine("Hello, World!");變數與基本型別
每個變數都有靜態型別。var 讓編譯器根據值推論型別。實值型別(數字、bool、struct)直接保存資料;參考型別(string、類別、陣列)則指向一個物件。
| 型別 | 範例 | 說明 |
|---|---|---|
int | int n = 42; | 32 位元整數 |
long | long big = 10_000_000_000; | 64 位元整數 |
double | double x = 3.14; | 64 位元浮點數 |
decimal | decimal price = 19.99m; | 十進位,適合用於金額 |
bool | bool ok = true; | true 或 false |
char | char c = 'A'; | UTF-16 程式碼單元 |
string | string s = "hi"; | 不可變的文字 |
var name = "Ada";
int count = 7;
double avg = count / 2.0;
Console.WriteLine($"{name} has {count} items, avg {avg}"); // Ada has 7 items, avg 3.5
Console.WriteLine(count / 2); // 3 (integer division)
Console.WriteLine(int.Parse("12") + 1); // 13
string? nickname = null; // ? marks a nullable reference
Console.WriteLine(nickname ?? "none"); // none$"..." 是內插字串。新專案預設啟用可為 null 的參考型別,因此當可能為 null 的值未經檢查就被使用時,編譯器會發出警告。
流程控制與方法
int score = 72;
if (score >= 90) Console.WriteLine("A");
else if (score >= 70) Console.WriteLine("B"); // B
else Console.WriteLine("C");
for (int i = 0; i < 3; i++) Console.Write($"{Square(i)} "); // 0 1 4
Console.WriteLine();
foreach (var fruit in new[] { "apple", "pear" }) Console.WriteLine(fruit);
string day = "SAT";
string kind = day switch
{
"SAT" or "SUN" => "weekend",
_ => "weekday",
};
Console.WriteLine(kind); // weekend
Console.WriteLine(Greet("Lin")); // Hello, Lin!
static int Square(int x) => x * x;
static string Greet(string name, string greeting = "Hello") => $"{greeting}, {name}!";switch 運算式與 or 模式屬於 C# 的模式比對。方法可以有預設參數值、具名引數(Greet(name: "Lin")),以及使用 => 的運算式主體。
類別、屬性與 record
類別擁有欄位、屬性(帶有 get 與 set 邏輯的欄位)與方法。record 是以值來判斷相等性的型別,非常適合不可變資料。
var acc = new Account("Ann");
acc.Deposit(50);
Console.WriteLine($"{acc.Owner}: {acc.Balance}"); // Ann: 50
var p1 = new Point(3, 4);
var p2 = p1 with { Y = 5 }; // copy with one change
Console.WriteLine(p1); // Point { X = 3, Y = 4 }
Console.WriteLine(p1 == new Point(3, 4)); // True
public class Account
{
public string Owner { get; }
public decimal Balance { get; private set; }
public Account(string owner) => Owner = owner;
public void Deposit(decimal amount)
{
if (amount <= 0) throw new ArgumentException("amount must be positive");
Balance += amount;
}
}
public record Point(int X, int Y);型別宣告必須放在同一個檔案中最上層陳述式的後面。類別支援單一繼承(class Savings : Account),可實作任意數量的介面。
集合與 LINQ
System.Collections.Generic 中的泛型集合是日常使用的資料結構。LINQ(Language Integrated Query,語言整合查詢)為每個集合加上 Where、Select、OrderBy 與 GroupBy 等方法。
var nums = new List<int> { 3, 1, 2, 5 };
nums.Add(4);
nums.Sort();
Console.WriteLine(string.Join(", ", nums)); // 1, 2, 3, 4, 5
var ages = new Dictionary<string, int> { ["ann"] = 31, ["bob"] = 25 };
ages["cy"] = 40;
if (ages.TryGetValue("bob", out int bobAge)) Console.WriteLine(bobAge); // 25
var evenSquares = nums.Where(n => n % 2 == 0).Select(n => n * n).ToList();
Console.WriteLine(string.Join(" ", evenSquares)); // 4 16
var oldest = ages.OrderByDescending(kv => kv.Value).First();
Console.WriteLine(oldest.Key); // cy其他常見的集合還有存放不重複項目的 HashSet<T>、Queue<T>、Stack<T>,以及 int[] 這類固定大小的陣列。
招牌特色:async 與 await
C# 率先引入了後來被許多語言採用的 async/await 模型。async 方法會回傳 Task,並且可以 await 網路請求或讀取檔案這類耗時的操作,而不會阻塞執行緒。
using System.Net.Http;
using var http = new HttpClient();
var sizes = await Task.WhenAll(
GetLengthAsync(http, "https://example.com"),
GetLengthAsync(http, "https://example.org"));
Console.WriteLine($"downloaded {sizes.Sum()} characters");
static async Task<int> GetLengthAsync(HttpClient http, string url)
{
string html = await http.GetStringAsync(url);
return html.Length;
}Task.WhenAll 會同時執行兩個請求並等待兩者都完成。using var 宣告會在作用域結束時釋放 HttpClient。
例外處理
錯誤即例外。請先捕捉特定型別,並用 finally 或 using 進行清理。對於常常不合法的輸入,TryParse 模式可以避免使用例外。
try
{
int age = int.Parse("abc");
}
catch (FormatException ex)
{
Console.WriteLine($"not a number: {ex.Message}");
}
finally
{
Console.WriteLine("done");
}
if (!int.TryParse("41", out int parsed)) parsed = 0;
Console.WriteLine(parsed); // 41完整的小程式:單字頻率統計
將主控台專案中的 Program.cs 換成這段程式碼,然後執行 dotnet run -- notes.txt。
using System.Text.RegularExpressions;
if (args.Length != 1)
{
Console.Error.WriteLine("usage: dotnet run -- FILE");
return 1;
}
try
{
string text = File.ReadAllText(args[0]).ToLowerInvariant();
var top = Regex.Matches(text, "[a-z']+")
.GroupBy(m => m.Value)
.Select(g => (Word: g.Key, Count: g.Count()))
.OrderByDescending(t => t.Count)
.Take(5);
foreach (var (word, count) in top)
Console.WriteLine($"{count,5} {word}");
return 0;
}
catch (FileNotFoundException)
{
Console.Error.WriteLine($"file not found: {args[0]}");
return 1;
}最上層陳述式可以讀取命令列的 args,也能回傳結束代碼。新專案透過隱含 using 會自動匯入 System.IO、System.Linq 與 System.Collections.Generic。
初學者常見錯誤
- 用
double處理金額;請改用decimal以避免二進位的捨入誤差。 - 忽略可為 null 的警告,這些警告最後會變成執行階段的
NullReferenceException。 - 在對同一個 list 的
foreach中修改List<T>,會拋出InvalidOperationException。 - 在長時間執行的應用程式中,為每個請求都建立新的
HttpClient。請重複使用同一個執行個體,或使用IHttpClientFactory。 - 忘記 LINQ 查詢是惰性執行的:除非呼叫
ToList(),否則每次列舉時查詢都會重新執行。
接下來學什麼
Microsoft Learn 提供官方的 C# 文件,包括語言導覽與互動式教學。接著可以學習用於網頁 API 的 ASP.NET Core、用於資料庫的 Entity Framework Core,或用於遊戲的 Unity,並使用 xUnit 或 NUnit 撰寫測試。Visual Studio、搭配 C# Dev Kit 的 VS Code,以及 JetBrains Rider 是常見的編輯器。
常見問題
C# 只能在 Windows 上使用嗎?
不是。現代 .NET 可在 Windows、macOS 與 Linux 上執行,C# 應用程式也能部署到 Linux 伺服器與容器。只有 WPF 與 Windows Forms 等部分桌面 UI 框架僅限 Windows。
C# 和 .NET 有什麼差別?
C# 是程式語言。.NET 則是用來編譯與執行 C# 程式碼(也包含 F# 與 Visual Basic)的執行環境與函式庫。
C# 和 Java 很像嗎?
在許多方面很像:兩者都是靜態型別、具垃圾回收、物件導向且採用 C 風格語法的語言。C# 另外加入了屬性、LINQ、async/await、實值型別的 struct 與 record 等功能。
C# 適合開發遊戲嗎?
適合。最廣泛使用的遊戲引擎之一 Unity 使用 C# 撰寫遊戲腳本,Godot 引擎也支援 C#。