學習目標
- • 了解 C# 的特色和 .NET 生態系統
- • 掌握基本語法和強型別系統
- • 學會物件導向程式設計概念
- • 掌握類別、物件、封裝和繼承
- • 學會例外處理和集合操作
- • 了解 LINQ 和非同步程式設計
- • 能夠開發現代化應用程式
第1課:C# 簡介與第一個程式
中級了解什麼是 C#,它的特色和 .NET 生態系統,並編寫你的第一個 C# 程式。
什麼是 C#?
C#(讀作 "C Sharp")是由微軟開發的現代化程式語言,於 2000 年首次發布。它是 .NET 平台的主要語言之一,結合了 C++ 的強大功能和 Visual Basic 的易用性。
C# 的核心特色:
- 強型別系統:編譯時期檢查型別,減少執行時錯誤
- 物件導向:完整支援封裝、繼承、多型
- 記憶體管理:自動垃圾回收,無需手動管理記憶體
- 跨平台:.NET Core/.NET 5+ 支援 Windows、macOS、Linux
- 豐富的 API:.NET 基礎類別庫提供大量功能
- 現代語法:支援 LINQ、async/await、泛型等現代特性
你的第一個 C# 程式:
// Program.cs
// 這是你的第一個 C# 程式
using System; // 引入 System 命名空間
namespace HelloWorld // 定義命名空間
{
class Program // 定義類別
{
// Main 方法是程式的進入點
static void Main(string[] args)
{
// 在控制台輸出文字
Console.WriteLine("Hello, World!");
Console.WriteLine("歡迎來到 C# 的世界!");
Console.WriteLine("C# 是一種現代化的程式語言");
// 宣告和使用變數
string language = "C#";
int year = 2000;
double version = 10.0;
bool isModern = true;
// 使用字串插值輸出變數
Console.WriteLine($"程式語言:{language}");
Console.WriteLine($"發布年份:{year}");
Console.WriteLine($"目前版本:{version}");
Console.WriteLine($"是否現代化:{isModern}");
// 等待使用者按鍵(防止程式立即結束)
Console.WriteLine("\n按任意鍵結束程式...");
Console.ReadKey();
}
}
}
程式碼解釋:
- using System:引入 System 命名空間,提供基本功能如 Console
- namespace:命名空間用來組織程式碼,避免名稱衝突
- class Program:定義一個類別,C# 中所有程式碼都必須在類別內
- static void Main:程式的進入點,CLR 會從這裡開始執行
- Console.WriteLine:在控制台輸出文字並換行
- $"":字串插值,可以在字串中嵌入變數
- Console.ReadKey:等待使用者按鍵
.NET 生態系統:
.NET Framework:Windows 專用的原始版本
.NET Core:跨平台的開源版本
.NET 5/6/7/8:統一的跨平台版本
CLR:Common Language Runtime,負責執行 .NET 程式
💡 實作練習
修改程式碼,讓它顯示你的個人資訊:姓名、年齡、居住城市,體驗 C# 變數和字串插值的使用!
C# 的應用領域:
🖥️ 桌面應用
WPF、WinForms、WinUI
🌐 Web 開發
ASP.NET Core、Blazor
📱 行動應用
Xamarin、.NET MAUI
🎮 遊戲開發
Unity 遊戲引擎
第2課:變數與資料型別
中級學習 C# 的型別系統、變數宣告和型別轉換。
程式碼範例:
using System;
class DataTypes
{
static void Main()
{
// 基本資料型別
int age = 25; // 整數
double height = 175.5; // 雙精度浮點數
float weight = 70.5f; // 單精度浮點數
char grade = 'A'; // 字元
string name = "小明"; // 字串
bool isStudent = true; // 布林值
// var 關鍵字 (型別推斷)
var city = "台北"; // 編譯器推斷為 string
var score = 95; // 編譯器推斷為 int
// 常數
const double PI = 3.14159;
// 顯示資訊
Console.WriteLine($"姓名:{name}");
Console.WriteLine($"年齡:{age}");
Console.WriteLine($"身高:{height} 公分");
Console.WriteLine($"體重:{weight} 公斤");
Console.WriteLine($"等級:{grade}");
Console.WriteLine($"是學生:{isStudent}");
Console.WriteLine($"城市:{city}");
Console.WriteLine($"分數:{score}");
Console.WriteLine($"圓周率:{PI}");
}
}
第3課:控制流程與陣列
進階學習 C# 的條件判斷、迴圈控制和陣列操作。
條件判斷:
using System;
class ControlFlow
{
static void Main()
{
// if-else 條件判斷
int score = 85;
if (score >= 90)
{
Console.WriteLine("等級:A");
}
else if (score >= 80)
{
Console.WriteLine("等級:B");
}
else if (score >= 70)
{
Console.WriteLine("等級:C");
}
else if (score >= 60)
{
Console.WriteLine("等級:D");
}
else
{
Console.WriteLine("等級:F");
}
// switch 語句
string dayOfWeek = "Monday";
switch (dayOfWeek)
{
case "Monday":
Console.WriteLine("星期一 - 新的一週開始!");
break;
case "Tuesday":
Console.WriteLine("星期二 - 繼續努力!");
break;
case "Wednesday":
Console.WriteLine("星期三 - 週中了!");
break;
case "Thursday":
Console.WriteLine("星期四 - 快到週末了!");
break;
case "Friday":
Console.WriteLine("星期五 - 週末即將到來!");
break;
case "Saturday":
case "Sunday":
Console.WriteLine("週末 - 休息時間!");
break;
default:
Console.WriteLine("無效的日期");
break;
}
// 三元運算子
int age = 20;
string status = (age >= 18) ? "成年人" : "未成年";
Console.WriteLine($"年齡 {age}:{status}");
// 邏輯運算子
bool hasLicense = true;
bool hasInsurance = true;
if (hasLicense && hasInsurance)
{
Console.WriteLine("可以開車");
}
else if (hasLicense || hasInsurance)
{
Console.WriteLine("需要補齊證件");
}
else
{
Console.WriteLine("不能開車");
}
// null 條件運算子 (C# 6.0+)
string name = null;
int? nameLength = name?.Length; // 如果 name 為 null,結果也是 null
Console.WriteLine($"姓名長度:{nameLength ?? 0}"); // ?? 是 null 合併運算子
}
}
迴圈控制:
using System;
class Loops
{
static void Main()
{
Console.WriteLine("=== for 迴圈 ===");
// for 迴圈
for (int i = 1; i <= 5; i++)
{
Console.WriteLine($"第 {i} 次迴圈");
}
Console.WriteLine("\n=== while 迴圈 ===");
// while 迴圈
int count = 1;
while (count <= 3)
{
Console.WriteLine($"while 迴圈第 {count} 次");
count++;
}
Console.WriteLine("\n=== do-while 迴圈 ===");
// do-while 迴圈
int number = 1;
do
{
Console.WriteLine($"do-while 迴圈第 {number} 次");
number++;
} while (number <= 3);
Console.WriteLine("\n=== foreach 迴圈 ===");
// foreach 迴圈(用於陣列和集合)
string[] fruits = { "蘋果", "香蕉", "橘子" };
foreach (string fruit in fruits)
{
Console.WriteLine($"水果:{fruit}");
}
Console.WriteLine("\n=== 巢狀迴圈 ===");
// 巢狀迴圈 - 九九乘法表
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= 3; j++)
{
Console.Write($"{i} x {j} = {i * j}\t");
}
Console.WriteLine();
}
Console.WriteLine("\n=== break 和 continue ===");
// break 和 continue
for (int i = 1; i <= 10; i++)
{
if (i == 5)
{
Console.WriteLine("跳過 5");
continue; // 跳過當前迭代
}
if (i == 8)
{
Console.WriteLine("在 8 處停止");
break; // 跳出迴圈
}
Console.WriteLine($"數字:{i}");
}
Console.WriteLine("\n=== 尋找質數 ===");
// 實用範例:尋找質數
int limit = 20;
Console.WriteLine($"1 到 {limit} 的質數:");
for (int num = 2; num <= limit; num++)
{
bool isPrime = true;
for (int i = 2; i <= Math.Sqrt(num); i++)
{
if (num % i == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
Console.Write($"{num} ");
}
}
Console.WriteLine();
}
}
陣列基礎:
using System;
using System.Linq; // 用於 LINQ 方法
class Arrays
{
static void Main()
{
Console.WriteLine("=== 陣列宣告和初始化 ===");
// 陣列宣告方式
int[] numbers1 = new int[5]; // 宣告大小為 5 的陣列
int[] numbers2 = { 1, 2, 3, 4, 5 }; // 直接初始化
int[] numbers3 = new int[] { 10, 20, 30, 40, 50 }; // 另一種初始化方式
// 字串陣列
string[] names = { "小明", "小華", "小美", "小強" };
Console.WriteLine($"numbers2 陣列長度:{numbers2.Length}");
Console.WriteLine("\n=== 存取陣列元素 ===");
// 存取和修改陣列元素
numbers1[0] = 100;
numbers1[1] = 200;
numbers1[2] = 300;
Console.WriteLine($"第一個元素:{numbers1[0]}");
Console.WriteLine($"最後一個元素:{numbers2[numbers2.Length - 1]}");
Console.WriteLine("\n=== 遍歷陣列 ===");
// 使用 for 迴圈
Console.WriteLine("使用 for 迴圈:");
for (int i = 0; i < numbers2.Length; i++)
{
Console.WriteLine($"索引 {i}:{numbers2[i]}");
}
// 使用 foreach 迴圈
Console.WriteLine("\n使用 foreach 迴圈:");
foreach (int number in numbers2)
{
Console.WriteLine($"數字:{number}");
}
Console.WriteLine("\n=== 陣列操作 ===");
int[] scores = { 85, 92, 78, 96, 88, 73, 91 };
// 計算總分和平均分
int total = 0;
foreach (int score in scores)
{
total += score;
}
double average = (double)total / scores.Length;
Console.WriteLine($"總分:{total}");
Console.WriteLine($"平均分:{average:F2}");
// 尋找最大值和最小值
int max = scores[0];
int min = scores[0];
foreach (int score in scores)
{
if (score > max) max = score;
if (score < min) min = score;
}
Console.WriteLine($"最高分:{max}");
Console.WriteLine($"最低分:{min}");
// 使用 LINQ 方法(更簡潔)
Console.WriteLine("\n=== 使用 LINQ 方法 ===");
Console.WriteLine($"LINQ 總分:{scores.Sum()}");
Console.WriteLine($"LINQ 平均分:{scores.Average():F2}");
Console.WriteLine($"LINQ 最高分:{scores.Max()}");
Console.WriteLine($"LINQ 最低分:{scores.Min()}");
Console.WriteLine($"及格人數:{scores.Count(s => s >= 60)}");
// 排序
Array.Sort(scores);
Console.WriteLine("\n排序後的分數:");
foreach (int score in scores)
{
Console.Write($"{score} ");
}
Console.WriteLine();
// 搜尋
int searchScore = 85;
int index = Array.IndexOf(scores, searchScore);
if (index >= 0)
{
Console.WriteLine($"分數 {searchScore} 在索引 {index}");
}
else
{
Console.WriteLine($"找不到分數 {searchScore}");
}
}
}
多維陣列:
using System;
class MultiDimensionalArrays
{
static void Main()
{
Console.WriteLine("=== 二維陣列 ===");
// 二維陣列宣告和初始化
int[,] matrix = new int[3, 4]; // 3 行 4 列
int[,] numbers = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
// 存取二維陣列元素
matrix[0, 0] = 100;
matrix[1, 2] = 200;
Console.WriteLine($"matrix[0,0] = {matrix[0, 0]}");
Console.WriteLine($"numbers[1,2] = {numbers[1, 2]}");
// 遍歷二維陣列
Console.WriteLine("\n二維陣列內容:");
for (int i = 0; i < numbers.GetLength(0); i++) // GetLength(0) 取得第一維長度
{
for (int j = 0; j < numbers.GetLength(1); j++) // GetLength(1) 取得第二維長度
{
Console.Write($"{numbers[i, j]}\t");
}
Console.WriteLine();
}
Console.WriteLine("\n=== 鋸齒陣列 (Jagged Array) ===");
// 鋸齒陣列:陣列的陣列
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[] { 1, 2 };
jaggedArray[1] = new int[] { 3, 4, 5, 6 };
jaggedArray[2] = new int[] { 7, 8, 9 };
// 或者直接初始化
int[][] jaggedArray2 = {
new int[] { 1, 2 },
new int[] { 3, 4, 5, 6 },
new int[] { 7, 8, 9 }
};
Console.WriteLine("鋸齒陣列內容:");
for (int i = 0; i < jaggedArray2.Length; i++)
{
Console.Write($"第 {i + 1} 行:");
for (int j = 0; j < jaggedArray2[i].Length; j++)
{
Console.Write($"{jaggedArray2[i][j]} ");
}
Console.WriteLine();
}
Console.WriteLine("\n=== 實用範例:成績表 ===");
// 學生成績表
string[] students = { "小明", "小華", "小美" };
string[] subjects = { "數學", "英文", "物理" };
int[,] grades = {
{ 85, 92, 78 }, // 小明的成績
{ 90, 88, 95 }, // 小華的成績
{ 87, 91, 89 } // 小美的成績
};
// 顯示成績表
Console.Write("學生\t");
foreach (string subject in subjects)
{
Console.Write($"{subject}\t");
}
Console.WriteLine("平均");
for (int i = 0; i < students.Length; i++)
{
Console.Write($"{students[i]}\t");
int total = 0;
for (int j = 0; j < subjects.Length; j++)
{
Console.Write($"{grades[i, j]}\t");
total += grades[i, j];
}
double average = (double)total / subjects.Length;
Console.WriteLine($"{average:F1}");
}
// 計算各科平均
Console.WriteLine("\n各科平均分數:");
for (int j = 0; j < subjects.Length; j++)
{
int subjectTotal = 0;
for (int i = 0; i < students.Length; i++)
{
subjectTotal += grades[i, j];
}
double subjectAverage = (double)subjectTotal / students.Length;
Console.WriteLine($"{subjects[j]}:{subjectAverage:F1}");
}
}
}
💡 實作練習
建立一個簡單的學生管理系統,使用陣列儲存學生資料,實作新增、搜尋和統計功能!
第4課:物件導向程式設計
進階學習 C# 的類別、物件、封裝、繼承和多型等物件導向核心概念。
類別與物件基礎:
using System;
// 定義一個學生類別
public class Student
{
// 欄位 (Fields) - 私有資料
private string name;
private int age;
private double gpa;
// 屬性 (Properties) - 提供安全的存取方式
public string Name
{
get { return name; }
set
{
if (!string.IsNullOrEmpty(value))
name = value;
}
}
public int Age
{
get { return age; }
set
{
if (value >= 0 && value <= 150)
age = value;
}
}
public double GPA
{
get { return gpa; }
set
{
if (value >= 0.0 && value <= 4.0)
gpa = value;
}
}
// 自動屬性 (Auto-implemented Properties)
public string StudentId { get; set; }
public string Major { get; set; }
// 建構子 (Constructor)
public Student()
{
// 預設建構子
Name = "未知";
Age = 0;
GPA = 0.0;
StudentId = "000000";
Major = "未定";
}
public Student(string name, int age, string studentId)
{
Name = name;
Age = age;
StudentId = studentId;
GPA = 0.0;
Major = "未定";
}
public Student(string name, int age, string studentId, string major, double gpa)
{
Name = name;
Age = age;
StudentId = studentId;
Major = major;
GPA = gpa;
}
// 方法 (Methods)
public void Study(string subject)
{
Console.WriteLine($"{Name} 正在學習 {subject}");
}
public void TakeExam(string subject, double score)
{
Console.WriteLine($"{Name} 參加了 {subject} 考試,得分:{score}");
if (score >= 90)
Console.WriteLine("表現優秀!");
else if (score >= 70)
Console.WriteLine("表現良好!");
else
Console.WriteLine("需要更加努力!");
}
public string GetGradeLevel()
{
if (GPA >= 3.5) return "優等生";
else if (GPA >= 3.0) return "良好";
else if (GPA >= 2.0) return "及格";
else return "需要改進";
}
public void DisplayInfo()
{
Console.WriteLine($"=== 學生資訊 ===");
Console.WriteLine($"姓名:{Name}");
Console.WriteLine($"年齡:{Age}");
Console.WriteLine($"學號:{StudentId}");
Console.WriteLine($"主修:{Major}");
Console.WriteLine($"GPA:{GPA:F2}");
Console.WriteLine($"等級:{GetGradeLevel()}");
}
// 覆寫 ToString 方法
public override string ToString()
{
return $"學生[{Name}, {Age}歲, {Major}]";
}
}
// 使用範例
class Program
{
static void Main()
{
// 建立物件
Student student1 = new Student();
Student student2 = new Student("小明", 20, "S001");
Student student3 = new Student("小華", 21, "S002", "資訊工程", 3.8);
// 設定屬性
student1.Name = "小美";
student1.Age = 19;
student1.StudentId = "S003";
student1.Major = "電機工程";
student1.GPA = 3.5;
// 呼叫方法
student2.Study("程式設計");
student2.TakeExam("程式設計", 95);
// 顯示資訊
student1.DisplayInfo();
Console.WriteLine();
student2.DisplayInfo();
Console.WriteLine();
student3.DisplayInfo();
// 使用 ToString
Console.WriteLine($"\n所有學生:");
Console.WriteLine(student1);
Console.WriteLine(student2);
Console.WriteLine(student3);
}
}
繼承 (Inheritance):
using System;
// 基底類別 (Base Class)
public class Person
{
protected string name; // protected:子類別可以存取
protected int age;
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
// 虛擬方法 (Virtual Method) - 可以被子類別覆寫
public virtual void Introduce()
{
Console.WriteLine($"我是 {name},今年 {age} 歲");
}
public virtual void Work()
{
Console.WriteLine($"{name} 正在工作");
}
}
// 衍生類別 (Derived Class) - 學生
public class Student : Person
{
private string studentId;
private string major;
public string StudentId
{
get { return studentId; }
set { studentId = value; }
}
public string Major
{
get { return major; }
set { major = value; }
}
// 建構子:使用 base 呼叫父類別建構子
public Student(string name, int age, string studentId, string major)
: base(name, age)
{
this.studentId = studentId;
this.major = major;
}
// 覆寫父類別方法
public override void Introduce()
{
base.Introduce(); // 呼叫父類別的方法
Console.WriteLine($"我是學生,學號:{studentId},主修:{major}");
}
public override void Work()
{
Console.WriteLine($"學生 {name} 正在學習和做作業");
}
// 新增學生特有的方法
public void Study()
{
Console.WriteLine($"{name} 正在讀書");
}
public void TakeExam()
{
Console.WriteLine($"{name} 正在考試");
}
}
// 衍生類別 - 教師
public class Teacher : Person
{
private string employeeId;
private string department;
private double salary;
public string EmployeeId { get; set; }
public string Department { get; set; }
public double Salary { get; set; }
public Teacher(string name, int age, string employeeId, string department, double salary)
: base(name, age)
{
EmployeeId = employeeId;
Department = department;
Salary = salary;
}
public override void Introduce()
{
base.Introduce();
Console.WriteLine($"我是教師,員工編號:{EmployeeId},部門:{Department}");
}
public override void Work()
{
Console.WriteLine($"教師 {name} 正在教學和研究");
}
public void Teach(string subject)
{
Console.WriteLine($"{name} 正在教授 {subject}");
}
public void GradeExams()
{
Console.WriteLine($"{name} 正在批改考卷");
}
}
// 使用範例
class InheritanceExample
{
static void Main()
{
// 建立不同類型的物件
Person person = new Person("一般人", 30);
Student student = new Student("小明", 20, "S001", "資訊工程");
Teacher teacher = new Teacher("王老師", 35, "T001", "資訊系", 60000);
Console.WriteLine("=== 個別介紹 ===");
person.Introduce();
Console.WriteLine();
student.Introduce();
student.Study();
student.TakeExam();
Console.WriteLine();
teacher.Introduce();
teacher.Teach("程式設計");
teacher.GradeExams();
Console.WriteLine();
Console.WriteLine("=== 多型示範 ===");
// 多型:使用基底類別參考指向衍生類別物件
Person[] people = { person, student, teacher };
foreach (Person p in people)
{
p.Introduce(); // 會呼叫各自覆寫的方法
p.Work(); // 會呼叫各自覆寫的方法
Console.WriteLine();
}
Console.WriteLine("=== 型別檢查 ===");
foreach (Person p in people)
{
Console.WriteLine($"{p.Name} 的型別:{p.GetType().Name}");
// 使用 is 運算子檢查型別
if (p is Student s)
{
Console.WriteLine($" 這是學生,主修:{s.Major}");
}
else if (p is Teacher t)
{
Console.WriteLine($" 這是教師,部門:{t.Department}");
}
else
{
Console.WriteLine(" 這是一般人");
}
}
}
}
介面 (Interface) 與抽象類別:
using System;
using System.Collections.Generic;
// 介面定義
public interface IDrawable
{
void Draw();
void Move(int x, int y);
}
public interface IResizable
{
void Resize(double factor);
}
// 抽象類別
public abstract class Shape : IDrawable
{
protected string color;
protected int x, y;
public string Color
{
get { return color; }
set { color = value; }
}
public int X { get { return x; } }
public int Y { get { return y; } }
public Shape(string color, int x, int y)
{
this.color = color;
this.x = x;
this.y = y;
}
// 抽象方法:子類別必須實作
public abstract double CalculateArea();
public abstract double CalculatePerimeter();
// 虛擬方法:子類別可以選擇覆寫
public virtual void Move(int newX, int newY)
{
x = newX;
y = newY;
Console.WriteLine($"{GetType().Name} 移動到 ({x}, {y})");
}
// 介面方法的預設實作
public virtual void Draw()
{
Console.WriteLine($"繪製{color}的{GetType().Name}在位置({x}, {y})");
}
}
// 圓形類別
public class Circle : Shape, IResizable
{
private double radius;
public double Radius
{
get { return radius; }
set { radius = value > 0 ? value : 1; }
}
public Circle(string color, int x, int y, double radius) : base(color, x, y)
{
Radius = radius;
}
public override double CalculateArea()
{
return Math.PI * radius * radius;
}
public override double CalculatePerimeter()
{
return 2 * Math.PI * radius;
}
public override void Draw()
{
Console.WriteLine($"繪製{color}圓形,半徑:{radius},位置:({x}, {y})");
}
public void Resize(double factor)
{
radius *= factor;
Console.WriteLine($"圓形大小調整為原來的 {factor} 倍,新半徑:{radius:F2}");
}
}
// 矩形類別
public class Rectangle : Shape, IResizable
{
private double width, height;
public double Width
{
get { return width; }
set { width = value > 0 ? value : 1; }
}
public double Height
{
get { return height; }
set { height = value > 0 ? value : 1; }
}
public Rectangle(string color, int x, int y, double width, double height) : base(color, x, y)
{
Width = width;
Height = height;
}
public override double CalculateArea()
{
return width * height;
}
public override double CalculatePerimeter()
{
return 2 * (width + height);
}
public override void Draw()
{
Console.WriteLine($"繪製{color}矩形,寬:{width},高:{height},位置:({x}, {y})");
}
public void Resize(double factor)
{
width *= factor;
height *= factor;
Console.WriteLine($"矩形大小調整為原來的 {factor} 倍");
}
}
// 圖形管理器
public class ShapeManager
{
private List shapes = new List();
public void AddShape(Shape shape)
{
shapes.Add(shape);
Console.WriteLine($"新增了 {shape.GetType().Name}");
}
public void DrawAllShapes()
{
Console.WriteLine("=== 繪製所有圖形 ===");
foreach (Shape shape in shapes)
{
shape.Draw();
}
}
public void ShowAllAreas()
{
Console.WriteLine("=== 所有圖形面積 ===");
double totalArea = 0;
foreach (Shape shape in shapes)
{
double area = shape.CalculateArea();
Console.WriteLine($"{shape.GetType().Name}:{area:F2}");
totalArea += area;
}
Console.WriteLine($"總面積:{totalArea:F2}");
}
public void ResizeAllShapes(double factor)
{
Console.WriteLine($"=== 調整所有可調整大小的圖形 ===");
foreach (Shape shape in shapes)
{
if (shape is IResizable resizable)
{
resizable.Resize(factor);
}
}
}
}
// 使用範例
class InterfaceExample
{
static void Main()
{
// 建立圖形管理器
ShapeManager manager = new ShapeManager();
// 建立不同的圖形
Circle circle = new Circle("紅色", 10, 20, 5);
Rectangle rectangle = new Rectangle("藍色", 0, 0, 10, 8);
// 新增到管理器
manager.AddShape(circle);
manager.AddShape(rectangle);
// 繪製所有圖形
manager.DrawAllShapes();
Console.WriteLine();
// 顯示面積
manager.ShowAllAreas();
Console.WriteLine();
// 移動圖形
circle.Move(15, 25);
rectangle.Move(5, 5);
Console.WriteLine();
// 調整大小
manager.ResizeAllShapes(1.5);
Console.WriteLine();
// 再次顯示面積
manager.ShowAllAreas();
Console.WriteLine("\n=== 介面多型示範 ===");
// 使用介面參考
IDrawable[] drawables = { circle, rectangle };
foreach (IDrawable drawable in drawables)
{
drawable.Draw();
}
IResizable[] resizables = { circle, rectangle };
foreach (IResizable resizable in resizables)
{
resizable.Resize(0.8);
}
}
}
💡 實作練習
設計一個動物園管理系統,建立動物基底類別和不同動物子類別,實作餵食和表演介面!
第5課:LINQ 與集合操作
進階學習 C# 的 LINQ 查詢語法和強大的集合操作功能。
集合基礎 - List 和 Dictionary:
using System;
using System.Collections.Generic;
using System.Linq;
class CollectionsBasics
{
static void Main()
{
Console.WriteLine("=== List<T> 基礎操作 ===");
// 建立和初始化 List
List<string> fruits = new List<string>();
fruits.Add("蘋果");
fruits.Add("香蕉");
fruits.Add("橘子");
// 使用集合初始化器
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Console.WriteLine($"水果數量:{fruits.Count}");
Console.WriteLine($"第一個水果:{fruits[0]}");
// 遍歷 List
Console.WriteLine("所有水果:");
foreach (string fruit in fruits)
{
Console.WriteLine($"- {fruit}");
}
// List 操作
fruits.Insert(1, "葡萄"); // 在索引1插入
fruits.Remove("香蕉"); // 移除第一個符合的項目
fruits.RemoveAt(0); // 移除索引0的項目
Console.WriteLine($"操作後的水果:{string.Join(", ", fruits)}");
Console.WriteLine("\n=== Dictionary<TKey, TValue> 基礎操作 ===");
// 建立字典
Dictionary<string, int> studentGrades = new Dictionary<string, int>
{
{"小明", 85},
{"小華", 92},
{"小美", 78},
{"小強", 96}
};
// 新增和修改
studentGrades["小麗"] = 88; // 新增
studentGrades["小明"] = 90; // 修改
Console.WriteLine($"學生人數:{studentGrades.Count}");
Console.WriteLine($"小華的成績:{studentGrades["小華"]}");
// 安全存取
if (studentGrades.TryGetValue("小王", out int grade))
{
Console.WriteLine($"小王的成績:{grade}");
}
else
{
Console.WriteLine("找不到小王的成績");
}
// 遍歷字典
Console.WriteLine("所有學生成績:");
foreach (KeyValuePair<string, int> kvp in studentGrades)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}分");
}
// 只遍歷鍵或值
Console.WriteLine("學生名單:" + string.Join(", ", studentGrades.Keys));
Console.WriteLine("成績列表:" + string.Join(", ", studentGrades.Values));
Console.WriteLine("\n=== HashSet<T> 和 Queue<T> ===");
// HashSet - 不重複集合
HashSet<string> uniqueFruits = new HashSet<string> { "蘋果", "香蕉", "橘子", "蘋果" };
Console.WriteLine($"唯一水果:{string.Join(", ", uniqueFruits)}"); // 不會有重複的蘋果
// Queue - 佇列 (先進先出)
Queue<string> taskQueue = new Queue<string>();
taskQueue.Enqueue("任務1");
taskQueue.Enqueue("任務2");
taskQueue.Enqueue("任務3");
Console.WriteLine("處理任務:");
while (taskQueue.Count > 0)
{
string task = taskQueue.Dequeue();
Console.WriteLine($"執行:{task}");
}
// Stack - 堆疊 (後進先出)
Stack<string> history = new Stack<string>();
history.Push("頁面1");
history.Push("頁面2");
history.Push("頁面3");
Console.WriteLine("瀏覽歷史(後退):");
while (history.Count > 0)
{
string page = history.Pop();
Console.WriteLine($"回到:{page}");
}
}
}
LINQ 基礎查詢:
using System;
using System.Collections.Generic;
using System.Linq;
// 學生類別
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Major { get; set; }
public double GPA { get; set; }
public List<int> Scores { get; set; }
public Student(string name, int age, string major, double gpa, params int[] scores)
{
Name = name;
Age = age;
Major = major;
GPA = gpa;
Scores = scores.ToList();
}
public override string ToString()
{
return $"{Name}({Age}歲, {Major}, GPA:{GPA})";
}
}
class LinqBasics
{
static void Main()
{
// 建立測試資料
List<Student> students = new List<Student>
{
new Student("小明", 20, "資訊工程", 3.8, 85, 92, 78),
new Student("小華", 21, "電機工程", 3.5, 90, 88, 95),
new Student("小美", 19, "資訊工程", 3.9, 87, 91, 89),
new Student("小強", 22, "機械工程", 3.2, 75, 80, 85),
new Student("小麗", 20, "電機工程", 3.7, 92, 89, 94)
};
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Console.WriteLine("=== Where - 篩選 ===");
// 篩選 GPA 大於 3.5 的學生
var highGpaStudents = students.Where(s => s.GPA > 3.5);
Console.WriteLine("GPA > 3.5 的學生:");
foreach (var student in highGpaStudents)
{
Console.WriteLine($" {student}");
}
// 篩選偶數
var evenNumbers = numbers.Where(n => n % 2 == 0);
Console.WriteLine($"偶數:{string.Join(", ", evenNumbers)}");
Console.WriteLine("\n=== Select - 投影 ===");
// 選取學生姓名
var studentNames = students.Select(s => s.Name);
Console.WriteLine($"學生姓名:{string.Join(", ", studentNames)}");
// 建立匿名物件
var studentInfo = students.Select(s => new { s.Name, s.Major, s.GPA });
Console.WriteLine("學生基本資訊:");
foreach (var info in studentInfo)
{
Console.WriteLine($" {info.Name} - {info.Major} (GPA: {info.GPA})");
}
// 數字平方
var squares = numbers.Select(n => n * n);
Console.WriteLine($"平方數:{string.Join(", ", squares)}");
Console.WriteLine("\n=== OrderBy - 排序 ===");
// 按 GPA 排序
var sortedByGpa = students.OrderBy(s => s.GPA);
Console.WriteLine("按 GPA 升序排列:");
foreach (var student in sortedByGpa)
{
Console.WriteLine($" {student}");
}
// 按 GPA 降序排列
var sortedByGpaDesc = students.OrderByDescending(s => s.GPA);
Console.WriteLine("\n按 GPA 降序排列:");
foreach (var student in sortedByGpaDesc)
{
Console.WriteLine($" {student}");
}
// 多重排序:先按主修,再按 GPA
var multiSort = students.OrderBy(s => s.Major).ThenByDescending(s => s.GPA);
Console.WriteLine("\n按主修分組,再按 GPA 降序:");
foreach (var student in multiSort)
{
Console.WriteLine($" {student}");
}
Console.WriteLine("\n=== GroupBy - 分組 ===");
// 按主修分組
var groupedByMajor = students.GroupBy(s => s.Major);
Console.WriteLine("按主修分組:");
foreach (var group in groupedByMajor)
{
Console.WriteLine($" {group.Key}:");
foreach (var student in group)
{
Console.WriteLine($" {student}");
}
}
Console.WriteLine("\n=== 聚合函數 ===");
// 統計資訊
Console.WriteLine($"學生總數:{students.Count()}");
Console.WriteLine($"平均 GPA:{students.Average(s => s.GPA):F2}");
Console.WriteLine($"最高 GPA:{students.Max(s => s.GPA)}");
Console.WriteLine($"最低 GPA:{students.Min(s => s.GPA)}");
Console.WriteLine($"GPA 總和:{students.Sum(s => s.GPA):F2}");
// 條件統計
Console.WriteLine($"資訊工程學生數:{students.Count(s => s.Major == "資訊工程")}");
Console.WriteLine($"是否有 GPA 滿分學生:{students.Any(s => s.GPA == 4.0)}");
Console.WriteLine($"是否所有學生都及格:{students.All(s => s.GPA >= 2.0)}");
}
}
LINQ 進階操作:
using System;
using System.Collections.Generic;
using System.Linq;
// 課程類別
public class Course
{
public string Name { get; set; }
public string Department { get; set; }
public int Credits { get; set; }
public Course(string name, string department, int credits)
{
Name = name;
Department = department;
Credits = credits;
}
public override string ToString()
{
return $"{Name}({Department}, {Credits}學分)";
}
}
// 選課記錄
public class Enrollment
{
public string StudentName { get; set; }
public string CourseName { get; set; }
public int Score { get; set; }
public Enrollment(string studentName, string courseName, int score)
{
StudentName = studentName;
CourseName = courseName;
Score = score;
}
}
class AdvancedLinq
{
static void Main()
{
// 測試資料
List<Student> students = new List<Student>
{
new Student("小明", 20, "資訊工程", 3.8, 85, 92, 78),
new Student("小華", 21, "電機工程", 3.5, 90, 88, 95),
new Student("小美", 19, "資訊工程", 3.9, 87, 91, 89),
new Student("小強", 22, "機械工程", 3.2, 75, 80, 85)
};
List<Course> courses = new List<Course>
{
new Course("程式設計", "資訊工程", 3),
new Course("資料結構", "資訊工程", 3),
new Course("電路學", "電機工程", 4),
new Course("工程數學", "電機工程", 3),
new Course("機械設計", "機械工程", 4)
};
List<Enrollment> enrollments = new List<Enrollment>
{
new Enrollment("小明", "程式設計", 85),
new Enrollment("小明", "資料結構", 92),
new Enrollment("小華", "電路學", 90),
new Enrollment("小華", "工程數學", 88),
new Enrollment("小美", "程式設計", 87),
new Enrollment("小強", "機械設計", 75)
};
Console.WriteLine("=== Join - 聯結操作 ===");
// 內部聯結:學生和他們的選課記錄
var studentEnrollments = students.Join(
enrollments,
student => student.Name,
enrollment => enrollment.StudentName,
(student, enrollment) => new
{
StudentName = student.Name,
Major = student.Major,
Course = enrollment.CourseName,
Score = enrollment.Score
});
Console.WriteLine("學生選課記錄:");
foreach (var record in studentEnrollments)
{
Console.WriteLine($" {record.StudentName}({record.Major}) - {record.Course}: {record.Score}分");
}
Console.WriteLine("\n=== SelectMany - 扁平化 ===");
// 取得所有學生的所有分數
var allScores = students.SelectMany(s => s.Scores);
Console.WriteLine($"所有分數:{string.Join(", ", allScores)}");
// 帶索引的扁平化
var studentScoreDetails = students.SelectMany(
(student, index) => student.Scores.Select(score => new
{
StudentIndex = index,
StudentName = student.Name,
Score = score
}));
Console.WriteLine("學生分數詳細:");
foreach (var detail in studentScoreDetails.Take(5)) // 只顯示前5筆
{
Console.WriteLine($" 學生{detail.StudentIndex}: {detail.StudentName} - {detail.Score}分");
}
Console.WriteLine("\n=== 集合操作 ===");
List<string> list1 = new List<string> { "A", "B", "C", "D" };
List<string> list2 = new List<string> { "C", "D", "E", "F" };
// 聯集
var union = list1.Union(list2);
Console.WriteLine($"聯集:{string.Join(", ", union)}");
// 交集
var intersect = list1.Intersect(list2);
Console.WriteLine($"交集:{string.Join(", ", intersect)}");
// 差集
var except = list1.Except(list2);
Console.WriteLine($"差集 (list1 - list2):{string.Join(", ", except)}");
Console.WriteLine("\n=== 分頁和跳過 ===");
// 分頁顯示學生
int pageSize = 2;
for (int page = 0; page < (students.Count + pageSize - 1) / pageSize; page++)
{
var pageStudents = students.Skip(page * pageSize).Take(pageSize);
Console.WriteLine($"第 {page + 1} 頁:");
foreach (var student in pageStudents)
{
Console.WriteLine($" {student}");
}
}
Console.WriteLine("\n=== 複雜查詢範例 ===");
// 找出每個系 GPA 最高的學生
var topStudentsByMajor = students
.GroupBy(s => s.Major)
.Select(g => g.OrderByDescending(s => s.GPA).First())
.OrderBy(s => s.Major);
Console.WriteLine("各系 GPA 最高的學生:");
foreach (var student in topStudentsByMajor)
{
Console.WriteLine($" {student}");
}
// 統計每個系的平均 GPA
var majorStats = students
.GroupBy(s => s.Major)
.Select(g => new
{
Major = g.Key,
Count = g.Count(),
AverageGPA = g.Average(s => s.GPA),
MaxGPA = g.Max(s => s.GPA),
MinGPA = g.Min(s => s.GPA)
})
.OrderByDescending(stat => stat.AverageGPA);
Console.WriteLine("\n各系統計資訊:");
foreach (var stat in majorStats)
{
Console.WriteLine($" {stat.Major}:");
Console.WriteLine($" 學生數:{stat.Count}");
Console.WriteLine($" 平均 GPA:{stat.AverageGPA:F2}");
Console.WriteLine($" 最高 GPA:{stat.MaxGPA}");
Console.WriteLine($" 最低 GPA:{stat.MinGPA}");
}
Console.WriteLine("\n=== LINQ 查詢語法 ===");
// 使用查詢語法(類似 SQL)
var queryResult = from student in students
where student.GPA > 3.5
orderby student.GPA descending
select new { student.Name, student.Major, student.GPA };
Console.WriteLine("查詢語法結果(GPA > 3.5):");
foreach (var result in queryResult)
{
Console.WriteLine($" {result.Name} - {result.Major} (GPA: {result.GPA})");
}
}
}
💡 實作練習
建立一個電商系統,使用 LINQ 查詢商品、計算銷售統計、分析客戶購買行為!
第6課:非同步程式設計
進階學習 C# 的 async/await 非同步程式設計,提升應用程式的響應性和效能。
async/await 基礎:
using System;
using System.Threading.Tasks;
using System.Threading;
class AsyncBasics
{
static async Task Main(string[] args)
{
Console.WriteLine("=== 基本 async/await 示範 ===");
// 同步方法呼叫
Console.WriteLine("開始同步操作...");
SynchronousMethod();
Console.WriteLine("同步操作完成");
Console.WriteLine("\n開始非同步操作...");
// 非同步方法呼叫
await AsynchronousMethod();
Console.WriteLine("非同步操作完成");
Console.WriteLine("\n=== 多個非同步操作 ===");
await MultipleAsyncOperations();
Console.WriteLine("\n=== 並行執行 ===");
await ParallelAsyncOperations();
}
// 同步方法
static void SynchronousMethod()
{
Console.WriteLine(" 執行同步任務...");
Thread.Sleep(2000); // 模擬耗時操作
Console.WriteLine(" 同步任務完成");
}
// 非同步方法
static async Task AsynchronousMethod()
{
Console.WriteLine(" 開始非同步任務...");
await Task.Delay(2000); // 非同步等待
Console.WriteLine(" 非同步任務完成");
}
// 有回傳值的非同步方法
static async Task<string> GetDataAsync()
{
Console.WriteLine(" 正在取得資料...");
await Task.Delay(1000);
return "重要資料";
}
// 多個非同步操作(順序執行)
static async Task MultipleAsyncOperations()
{
Console.WriteLine("順序執行多個非同步操作:");
string data1 = await GetDataAsync();
Console.WriteLine($" 取得資料1:{data1}");
string data2 = await GetDataAsync();
Console.WriteLine($" 取得資料2:{data2}");
string data3 = await GetDataAsync();
Console.WriteLine($" 取得資料3:{data3}");
}
// 並行執行非同步操作
static async Task ParallelAsyncOperations()
{
Console.WriteLine("並行執行多個非同步操作:");
// 同時啟動多個任務
Task<string> task1 = GetDataAsync();
Task<string> task2 = GetDataAsync();
Task<string> task3 = GetDataAsync();
// 等待所有任務完成
string[] results = await Task.WhenAll(task1, task2, task3);
for (int i = 0; i < results.Length; i++)
{
Console.WriteLine($" 並行結果{i + 1}:{results[i]}");
}
}
}
Task 和 Task<T>:
using System;
using System.Threading.Tasks;
using System.Threading;
class TaskExamples
{
static async Task Main()
{
Console.WriteLine("=== Task 建立和執行 ===");
// 方法1:Task.Run
Task task1 = Task.Run(() =>
{
Console.WriteLine($"Task1 在執行緒 {Thread.CurrentThread.ManagedThreadId} 執行");
Thread.Sleep(1000);
Console.WriteLine("Task1 完成");
});
// 方法2:Task.Factory.StartNew
Task task2 = Task.Factory.StartNew(() =>
{
Console.WriteLine($"Task2 在執行緒 {Thread.CurrentThread.ManagedThreadId} 執行");
Thread.Sleep(1000);
Console.WriteLine("Task2 完成");
});
// 方法3:new Task + Start
Task task3 = new Task(() =>
{
Console.WriteLine($"Task3 在執行緒 {Thread.CurrentThread.ManagedThreadId} 執行");
Thread.Sleep(1000);
Console.WriteLine("Task3 完成");
});
task3.Start();
// 等待所有任務完成
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("\n=== Task<T> 有回傳值的任務 ===");
// 建立有回傳值的任務
Task<int> calculationTask = Task.Run(() =>
{
Console.WriteLine("開始計算...");
Thread.Sleep(2000);
int result = 0;
for (int i = 1; i <= 100; i++)
{
result += i;
}
Console.WriteLine("計算完成");
return result;
});
Task<string> dataTask = Task.Run(async () =>
{
Console.WriteLine("開始取得資料...");
await Task.Delay(1500);
Console.WriteLine("資料取得完成");
return "重要資料內容";
});
// 等待並取得結果
int calculationResult = await calculationTask;
string dataResult = await dataTask;
Console.WriteLine($"計算結果:{calculationResult}");
Console.WriteLine($"資料結果:{dataResult}");
Console.WriteLine("\n=== 任務狀態和例外處理 ===");
await TaskStatusAndExceptionHandling();
Console.WriteLine("\n=== 取消令牌 ===");
await CancellationTokenExample();
}
static async Task TaskStatusAndExceptionHandling()
{
// 正常完成的任務
Task<string> successTask = Task.Run(async () =>
{
await Task.Delay(1000);
return "成功完成";
});
// 會拋出例外的任務
Task<string> faultedTask = Task.Run<string>(() =>
{
Thread.Sleep(500);
throw new InvalidOperationException("模擬錯誤");
});
try
{
string result1 = await successTask;
Console.WriteLine($"成功任務結果:{result1}");
Console.WriteLine($"任務狀態:{successTask.Status}");
}
catch (Exception ex)
{
Console.WriteLine($"成功任務發生例外:{ex.Message}");
}
try
{
string result2 = await faultedTask;
Console.WriteLine($"錯誤任務結果:{result2}");
}
catch (Exception ex)
{
Console.WriteLine($"錯誤任務發生例外:{ex.Message}");
Console.WriteLine($"任務狀態:{faultedTask.Status}");
}
}
static async Task CancellationTokenExample()
{
// 建立取消令牌
CancellationTokenSource cts = new CancellationTokenSource();
// 設定 3 秒後自動取消
cts.CancelAfter(TimeSpan.FromSeconds(3));
try
{
await LongRunningTask(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("任務被取消了");
}
finally
{
cts.Dispose();
}
}
static async Task LongRunningTask(CancellationToken cancellationToken)
{
Console.WriteLine("開始長時間執行的任務...");
for (int i = 1; i <= 10; i++)
{
// 檢查是否被取消
cancellationToken.ThrowIfCancellationRequested();
Console.WriteLine($" 步驟 {i}/10");
await Task.Delay(1000, cancellationToken);
}
Console.WriteLine("長時間任務完成");
}
}
實用非同步範例:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using System.Net.Http;
using System.IO;
// 模擬的資料服務
public class DataService
{
private static readonly Random random = new Random();
public async Task<string> GetUserDataAsync(int userId)
{
Console.WriteLine($"開始取得用戶 {userId} 的資料...");
// 模擬網路延遲
await Task.Delay(random.Next(1000, 3000));
// 模擬偶爾失敗
if (random.NextDouble() < 0.2) // 20% 機率失敗
{
throw new HttpRequestException($"無法取得用戶 {userId} 的資料");
}
return $"用戶{userId}的資料";
}
public async Task<List<string>> GetUserOrdersAsync(int userId)
{
Console.WriteLine($"開始取得用戶 {userId} 的訂單...");
await Task.Delay(random.Next(500, 1500));
return new List<string>
{
$"用戶{userId}的訂單1",
$"用戶{userId}的訂單2",
$"用戶{userId}的訂單3"
};
}
public async Task<string> GetUserPreferencesAsync(int userId)
{
Console.WriteLine($"開始取得用戶 {userId} 的偏好設定...");
await Task.Delay(random.Next(800, 2000));
return $"用戶{userId}的偏好設定";
}
}
// 檔案處理服務
public class FileService
{
public async Task<string> ReadFileAsync(string fileName)
{
Console.WriteLine($"開始讀取檔案:{fileName}");
// 模擬檔案讀取
await Task.Delay(1000);
return $"檔案 {fileName} 的內容";
}
public async Task WriteFileAsync(string fileName, string content)
{
Console.WriteLine($"開始寫入檔案:{fileName}");
// 模擬檔案寫入
await Task.Delay(800);
Console.WriteLine($"檔案 {fileName} 寫入完成");
}
public async Task<List<string>> ProcessMultipleFilesAsync(List<string> fileNames)
{
Console.WriteLine("開始並行處理多個檔案...");
// 建立所有檔案讀取任務
List<Task<string>> tasks = new List<Task<string>>();
foreach (string fileName in fileNames)
{
tasks.Add(ReadFileAsync(fileName));
}
// 等待所有任務完成
string[] results = await Task.WhenAll(tasks);
return new List<string>(results);
}
}
class PracticalAsyncExamples
{
static async Task Main()
{
DataService dataService = new DataService();
FileService fileService = new FileService();
Console.WriteLine("=== 順序執行 vs 並行執行 ===");
// 順序執行
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
await SequentialExecution(dataService);
stopwatch.Stop();
Console.WriteLine($"順序執行耗時:{stopwatch.ElapsedMilliseconds} ms\n");
// 並行執行
stopwatch.Restart();
await ParallelExecution(dataService);
stopwatch.Stop();
Console.WriteLine($"並行執行耗時:{stopwatch.ElapsedMilliseconds} ms\n");
Console.WriteLine("=== 錯誤處理和重試 ===");
await ErrorHandlingAndRetry(dataService);
Console.WriteLine("\n=== 檔案批次處理 ===");
await BatchFileProcessing(fileService);
Console.WriteLine("\n=== 進度報告 ===");
await ProgressReporting();
}
static async Task SequentialExecution(DataService dataService)
{
Console.WriteLine("順序執行:");
int userId = 1;
try
{
string userData = await dataService.GetUserDataAsync(userId);
Console.WriteLine($" 取得:{userData}");
List<string> orders = await dataService.GetUserOrdersAsync(userId);
Console.WriteLine($" 取得:{orders.Count} 個訂單");
string preferences = await dataService.GetUserPreferencesAsync(userId);
Console.WriteLine($" 取得:{preferences}");
}
catch (Exception ex)
{
Console.WriteLine($" 錯誤:{ex.Message}");
}
}
static async Task ParallelExecution(DataService dataService)
{
Console.WriteLine("並行執行:");
int userId = 2;
try
{
// 同時啟動所有任務
Task<string> userDataTask = dataService.GetUserDataAsync(userId);
Task<List<string>> ordersTask = dataService.GetUserOrdersAsync(userId);
Task<string> preferencesTask = dataService.GetUserPreferencesAsync(userId);
// 等待所有任務完成
await Task.WhenAll(userDataTask, ordersTask, preferencesTask);
Console.WriteLine($" 取得:{userDataTask.Result}");
Console.WriteLine($" 取得:{ordersTask.Result.Count} 個訂單");
Console.WriteLine($" 取得:{preferencesTask.Result}");
}
catch (Exception ex)
{
Console.WriteLine($" 錯誤:{ex.Message}");
}
}
static async Task ErrorHandlingAndRetry(DataService dataService)
{
int userId = 3;
int maxRetries = 3;
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
try
{
Console.WriteLine($"嘗試第 {attempt} 次取得用戶資料...");
string userData = await dataService.GetUserDataAsync(userId);
Console.WriteLine($"成功取得:{userData}");
break; // 成功就跳出迴圈
}
catch (Exception ex)
{
Console.WriteLine($"第 {attempt} 次嘗試失敗:{ex.Message}");
if (attempt == maxRetries)
{
Console.WriteLine("已達最大重試次數,放棄操作");
}
else
{
Console.WriteLine("等待後重試...");
await Task.Delay(1000); // 等待 1 秒後重試
}
}
}
}
static async Task BatchFileProcessing(FileService fileService)
{
List<string> fileNames = new List<string>
{
"file1.txt", "file2.txt", "file3.txt", "file4.txt", "file5.txt"
};
List<string> results = await fileService.ProcessMultipleFilesAsync(fileNames);
Console.WriteLine("批次處理結果:");
foreach (string result in results)
{
Console.WriteLine($" {result}");
}
}
static async Task ProgressReporting()
{
Console.WriteLine("開始進度報告任務...");
var progress = new Progress<int>(percentage =>
{
Console.WriteLine($"進度:{percentage}%");
});
await LongRunningTaskWithProgress(progress);
Console.WriteLine("進度報告任務完成");
}
static async Task LongRunningTaskWithProgress(IProgress<int> progress)
{
for (int i = 0; i <= 100; i += 10)
{
await Task.Delay(200); // 模擬工作
progress?.Report(i);
}
}
}
💡 實作練習
建立一個網路爬蟲程式,使用 async/await 並行下載多個網頁,並實作進度報告和錯誤處理!