C# 語法大全:從入門到精通

目錄

  1. C# 語言簡介

  2. 基礎語法與數據類型

  3. 控制流程語句

  4. 面向對象編程

  5. 高級特性與委託

  6. 泛型與集合

  7. LINQ 查詢

  8. 異步編程

  9. 屬性與反射

  10. C# 新特性


C# 語言簡介

什麼是 C#?

C#(發音為 "C Sharp")是由 Microsoft 開發的現代、面向對象、類型安全的編程語言,運行在 .NET 框架上。它結合了 C++ 的強大功能和 Visual Basic 的簡單易用性,成為 .NET 平台的主要開發語言。

C# 的發展歷史

  • 2000年:C# 1.0 發布,隨 .NET Framework 1.0

  • 2005年:C# 2.0 引入泛型

  • 2007年:C# 3.0 引入 LINQ

  • 2010年:C# 4.0 引入動態類型

  • 2012年:C# 5.0 引入 async/await

  • 2015年:C# 6.0 引入許多語法糖

  • 2017年:C# 7.0 引入模式匹配等

  • 2019年:C# 8.0 引入可空引用類型等

  • 2020年:C# 9.0 引入記錄類型等

  • 2021年:C# 10.0 引入全局 using 等

  • 2022年:C# 11.0 引入原始字符串字面量等

  • 2023年:C# 12.0 引入主構造函數等

第一個 C# 程序

csharp

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
            
            // 等待用戶輸入
            Console.ReadLine();
        }
    }
}

基礎語法與數據類型

變量與常量

csharp

using System;

class VariablesDemo
{
    public static void Demo()
    {
        // 變量聲明與初始化
        int age = 25;
        string name = "John Doe";
        double salary = 50000.50;
        bool isEmployed = true;
        char grade = 'A';
        
        // 常量聲明
        const double PI = 3.14159;
        const int DAYS_IN_WEEK = 7;
        
        // 隱式類型變量 (類型推斷)
        var message = "Hello World";  // 編譯器推斷為 string
        var count = 10;               // 編譯器推斷為 int
        var price = 9.99m;            // 編譯器推斷為 decimal
        
        // 顯示類型信息
        Console.WriteLine($"Type of message: {message.GetType()}");
        Console.WriteLine($"Type of count: {count.GetType()}");
        Console.WriteLine($"Type of price: {price.GetType()}");
        
        // 空值處理
        string? nullableString = null;  // 可空引用類型 (C# 8.0+)
        int? nullableInt = null;         // 可空值類型
        
        // 空條件運算符
        int length = nullableString?.Length ?? 0;
        Console.WriteLine($"String length: {length}");
    }
}

基本數據類型

值類型 (Value Types)

csharp

class ValueTypesDemo
{
    public static void Demo()
    {
        // 整數類型
        byte byteValue = 255;                    // 0 到 255
        sbyte sbyteValue = -128;                 // -128 到 127
        short shortValue = -32768;               // -32,768 到 32,767
        ushort ushortValue = 65535;              // 0 到 65,535
        int intValue = -2147483648;              // -2,147,483,648 到 2,147,483,647
        uint uintValue = 4294967295;             // 0 到 4,294,967,295
        long longValue = -9223372036854775808;   // -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
        ulong ulongValue = 18446744073709551615; // 0 到 18,446,744,073,709,551,615
        
        // 浮點數類型
        float floatValue = 3.14159f;             // 7 位精度
        double doubleValue = 3.14159265358979;   // 15-16 位精度
        decimal decimalValue = 3.14159265358979323846m; // 28-29 位精度
        
        // 其他值類型
        char charValue = 'A';
        bool boolValue = true;
        
        // 枚舉類型
        DayOfWeek today = DayOfWeek.Monday;
        
        // 結構體
        Point point = new Point(10, 20);
        
        Console.WriteLine($"Integer range: {int.MinValue} to {int.MaxValue}");
        Console.WriteLine($"Double range: {double.MinValue} to {double.MaxValue}");
    }
    
    // 結構體定義
    struct Point
    {
        public int X;
        public int Y;
        
        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }
    }
    
    // 枚舉定義
    enum DayOfWeek
    {
        Sunday,
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday
    }
}
引用類型 (Reference Types)

csharp

class ReferenceTypesDemo
{
    public static void Demo()
    {
        // 字符串
        string str1 = "Hello";
        string str2 = "World";
        string str3 = str1 + " " + str2;
        
        // 字符串插值 (C# 6.0+)
        string interpolated = $"{str1} {str2} from C#";
        
        // 原始字符串字面量 (C# 11.0+)
        string rawString = """
            This is a raw string literal.
            It can span multiple lines
            and doesn't need escape sequences for quotes: "Hello"
            """;
        
        // 對象
        object obj = "This is an object";
        
        // 動態類型
        dynamic dynamicVar = 10;
        dynamicVar = "Now I'm a string";
        dynamicVar = new { Name = "John", Age = 30 };
        
        // 數組
        int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
        string[] names = { "Alice", "Bob", "Charlie" };
        
        // 多維數組
        int[,] matrix = new int[3, 3]
        {
            { 1, 2, 3 },
            { 4, 5, 6 },
            { 7, 8, 9 }
        };
        
        // 交錯數組 (數組的數組)
        int[][] jaggedArray = new int[3][];
        jaggedArray[0] = new int[] { 1, 2, 3 };
        jaggedArray[1] = new int[] { 4, 5 };
        jaggedArray[2] = new int[] { 6, 7, 8, 9 };
    }
}

運算符

csharp

class OperatorsDemo
{
    public static void Demo()
    {
        int a = 10, b = 3;
        
        // 算術運算符
        int sum = a + b;        // 13
        int difference = a - b; // 7
        int product = a * b;    // 30
        int quotient = a / b;   // 3 (整數除法)
        int remainder = a % b;  // 1
        int increment = ++a;    // 先增加再賦值
        int decrement = --a;    // 先減少再賦值
        
        // 賦值運算符
        a += 5;     // a = a + 5
        a -= 3;     // a = a - 3
        a *= 2;     // a = a * 2
        a /= 4;     // a = a / 4
        a %= 3;     // a = a % 3
        
        // 比較運算符
        bool isEqual = (a == b);         // false
        bool notEqual = (a != b);        // true
        bool greaterThan = (a > b);      // true
        bool lessThan = (a < b);         // false
        bool greaterOrEqual = (a >= b);  // true
        bool lessOrEqual = (a <= b);     // false
        
        // 邏輯運算符
        bool x = true, y = false;
        bool andResult = x && y;    // false
        bool orResult = x || y;     // true
        bool notResult = !x;        // false
        
        // 位運算符
        int bitwiseAnd = a & b;
        int bitwiseOr = a | b;
        int bitwiseXor = a ^ b;
        int bitwiseNot = ~a;
        int leftShift = a << 2;
        int rightShift = a >> 2;
        
        // 三元條件運算符
        string result = (a > b) ? "a is greater" : "b is greater";
        
        // 空合並運算符 (??)
        string name1 = null;
        string displayName = name1 ?? "Default Name";
        
        // 空合並賦值運算符 (??=) (C# 8.0+)
        string name2 = null;
        name2 ??= "Default Value";
        
        // 空條件運算符 (?.)
        Person person = null;
        int? age = person?.Age;  // 如果 person 為 null,則 age 為 null
        
        // 索引運算符 (用於數組和集合)
        int[] numbers = { 1, 2, 3, 4, 5 };
        int first = numbers[0];
        numbers[2] = 10;
        
        // 範圍運算符 (C# 8.0+)
        var slice = numbers[1..4];  // 獲取索引 1 到 3 的元素
        var startSlice = numbers[..3];  // 從開始到索引 2
        var endSlice = numbers[2..];   // 從索引 2 到結束
        var allButLast = numbers[..^1]; // 除最後一個外的所有元素
        
        // ^ 運算符 (C# 8.0+)
        int last = numbers[^1];    // 最後一個元素
        int secondLast = numbers[^2]; // 倒數第二個元素
    }
}

class Person
{
    public int Age { get; set; }
}

類型轉換

csharp

class TypeConversionDemo
{
    public static void Demo()
    {
        // 隱式轉換 (小類型到大類型)
        int intValue = 100;
        long longValue = intValue;  // 隱式轉換
        
        // 顯式轉換 (大類型到小類型)
        double doubleValue = 9.78;
        int intFromDouble = (int)doubleValue;  // 顯式轉換,丟失小數部分
        
        // Convert 類
        string strNumber = "123";
        int convertedNumber = Convert.ToInt32(strNumber);
        
        // Parse 方法
        int parsedNumber = int.Parse("456");
        
        // TryParse 方法 (推薦)
        string input = "789";
        if (int.TryParse(input, out int result))
        {
            Console.WriteLine($"Parsed successfully: {result}");
        }
        else
        {
            Console.WriteLine("Parsing failed");
        }
        
        // 使用 System.Convert
        decimal decimalValue = Convert.ToDecimal("123.45");
        bool boolValue = Convert.ToBoolean("true");
        
        // 拆箱和裝箱
        int valueType = 42;
        object boxed = valueType;      // 裝箱
        int unboxed = (int)boxed;      // 拆箱
        
        // as 運算符 (安全轉換)
        object obj = "Hello";
        string str = obj as string;    // 如果轉換失敗,返回 null
        
        // is 運算符 (類型檢查)
        if (obj is string)
        {
            Console.WriteLine("obj is a string");
        }
        
        // 模式匹配中的 is (C# 7.0+)
        if (obj is string s)
        {
            Console.WriteLine($"obj is a string with value: {s}");
        }
        
        // 自定義轉換運算符
        Temperature temp = 25;  // 隱式轉換
        double celsius = (double)temp;  // 顯式轉換
    }
}

// 自定義類型轉換示例
class Temperature
{
    private double Celsius { get; }
    
    public Temperature(double celsius)
    {
        Celsius = celsius;
    }
    
    // 隱式轉換運算符
    public static implicit operator Temperature(double celsius)
    {
        return new Temperature(celsius);
    }
    
    // 顯式轉換運算符
    public static explicit operator double(Temperature temp)
    {
        return temp.Celsius;
    }
}

控制流程語句

條件語句

csharp

class ControlFlowDemo
{
    public static void Demo()
    {
        int score = 85;
        
        // if-else 語句
        if (score >= 90)
        {
            Console.WriteLine("Grade: A");
        }
        else if (score >= 80)
        {
            Console.WriteLine("Grade: B");
        }
        else if (score >= 70)
        {
            Console.WriteLine("Grade: C");
        }
        else
        {
            Console.WriteLine("Grade: F");
        }
        
        // 三元運算符
        string status = (score >= 60) ? "Pass" : "Fail";
        
        // switch 語句 (傳統)
        char grade = 'B';
        switch (grade)
        {
            case 'A':
                Console.WriteLine("Excellent");
                break;
            case 'B':
            case 'C':
                Console.WriteLine("Good");
                break;
            case 'D':
                Console.WriteLine("Pass");
                break;
            case 'F':
                Console.WriteLine("Fail");
                break;
            default:
                Console.WriteLine("Invalid grade");
                break;
        }
        
        // switch 表達式 (C# 8.0+)
        string gradeDescription = grade switch
        {
            'A' => "Excellent",
            'B' or 'C' => "Good",
            'D' => "Pass",
            'F' => "Fail",
            _ => "Invalid grade"
        };
        
        // 模式匹配的 switch (C# 7.0+)
        object obj = 42;
        switch (obj)
        {
            case int i when i > 0:
                Console.WriteLine($"Positive integer: {i}");
                break;
            case int i when i < 0:
                Console.WriteLine($"Negative integer: {i}");
                break;
            case string s:
                Console.WriteLine($"String: {s}");
                break;
            case null:
                Console.WriteLine("Null object");
                break;
            default:
                Console.WriteLine("Unknown type");
                break;
        }
    }
}

循環語句

csharp

class LoopsDemo
{
    public static void Demo()
    {
        // for 循環
        Console.WriteLine("for loop:");
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine($"i = {i}");
        }
        
        // 嵌套 for 循環
        Console.WriteLine("\nNested for loop (multiplication table):");
        for (int i = 1; i <= 3; i++)
        {
            for (int j = 1; j <= 3; j++)
            {
                Console.Write($"{i * j}\t");
            }
            Console.WriteLine();
        }
        
        // while 循環
        Console.WriteLine("\nwhile loop:");
        int counter = 0;
        while (counter < 3)
        {
            Console.WriteLine($"Counter: {counter}");
            counter++;
        }
        
        // do-while 循環 (至少執行一次)
        Console.WriteLine("\ndo-while loop:");
        int number;
        do
        {
            Console.Write("Enter a positive number: ");
            // 實際應用中這裡會有輸入邏輯
            number = 1; // 示例值
        } while (number <= 0);
        
        // foreach 循環
        Console.WriteLine("\nforeach loop:");
        string[] fruits = { "Apple", "Banana", "Cherry", "Date" };
        foreach (string fruit in fruits)
        {
            Console.WriteLine(fruit);
        }
        
        // 帶索引的 foreach (C# 8.0+)
        Console.WriteLine("\nforeach with index:");
        foreach (var (index, fruit) in fruits.Select((value, i) => (i, value)))
        {
            Console.WriteLine($"Index {index}: {fruit}");
        }
        
        // 循環控制語句
        Console.WriteLine("\nLoop control statements:");
        
        // break - 退出循環
        for (int i = 0; i < 10; i++)
        {
            if (i == 5)
                break;
            Console.WriteLine($"i = {i}");
        }
        
        // continue - 跳過本次迭代
        Console.WriteLine("\nContinue example:");
        for (int i = 0; i < 5; i++)
        {
            if (i == 2)
                continue;
            Console.WriteLine($"i = {i}");
        }
        
        // goto - 跳轉到標籤 (不推薦使用)
        Console.WriteLine("\nGoto example:");
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (i == 1 && j == 1)
                    goto endLoop;
                Console.WriteLine($"i={i}, j={j}");
            }
        }
        endLoop:
        Console.WriteLine("Loop ended with goto");
        
        // 無限循環
        /*
        while (true)
        {
            // 需要 break 語句來退出
            break;
        }
        */
        
        // 使用 Range 和 Indices 的循環 (C# 8.0+)
        Console.WriteLine("\nUsing ranges:");
        int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        
        foreach (var num in numbers[2..7])
        {
            Console.Write($"{num} ");
        }
        Console.WriteLine();
        
        // 反向循環
        Console.WriteLine("\nReverse loop:");
        for (int i = numbers.Length - 1; i >= 0; i--)
        {
            Console.Write($"{numbers[i]} ");
        }
        Console.WriteLine();
        
        // 使用 LINQ 的循環
        Console.WriteLine("\nUsing LINQ:");
        var evenNumbers = numbers.Where(n => n % 2 == 0);
        foreach (var num in evenNumbers)
        {
            Console.Write($"{num} ");
        }
        Console.WriteLine();
    }
}

面向對象編程

類和對象

csharp

// 基本類定義
public class Person
{
    // 字段 (Fields)
    private string _name;
    private int _age;
    
    // 靜態字段
    private static int _totalPeople = 0;
    
    // 常量
    public const string Species = "Homo sapiens";
    
    // 只讀字段
    private readonly DateTime _createdDate;
    
    // 構造函數
    public Person()
    {
        _name = "Unknown";
        _age = 0;
        _createdDate = DateTime.Now;
        _totalPeople++;
    }
    
    // 參數化構造函數
    public Person(string name, int age)
    {
        _name = name;
        _age = age;
        _createdDate = DateTime.Now;
        _totalPeople++;
    }
    
    // 主構造函數 (C# 12.0+)
    // public class Person(string name, int age) { ... }
    
    // 屬性 (Properties)
    public string Name
    {
        get { return _name; }
        set 
        { 
            if (!string.IsNullOrWhiteSpace(value))
                _name = value; 
        }
    }
    
    public int Age
    {
        get => _age;  // 表達式體成員 (C# 6.0+)
        set => _age = value >= 0 ? value : 0;
    }
    
    // 自動屬性
    public string Address { get; set; } = "Unknown";  // 自動初始值 (C# 6.0+)
    
    // 只讀自動屬性
    public DateTime BirthDate { get; }
    
    // 計算屬性
    public bool IsAdult => Age >= 18;
    
    // 靜態屬性
    public static int TotalPeople => _totalPeople;
    
    // 方法
    public void Introduce()
    {
        Console.WriteLine($"Hello, my name is {Name} and I'm {Age} years old.");
    }
    
    // 方法重載
    public void Introduce(string greeting)
    {
        Console.WriteLine($"{greeting}, I'm {Name}");
    }
    
    // 靜態方法
    public static void DisplaySpecies()
    {
        Console.WriteLine($"Species: {Species}");
    }
    
    // 虛方法 (可被子類重寫)
    public virtual void DisplayInfo()
    {
        Console.WriteLine($"Person: {Name}, {Age} years old");
    }
    
    // 析構函數
    ~Person()
    {
        _totalPeople--;
        Console.WriteLine($"Person {_name} is being destroyed");
    }
}

// 使用示例
class ClassDemo
{
    public static void Demo()
    {
        // 創建對象
        Person person1 = new Person();
        person1.Name = "Alice";
        person1.Age = 25;
        
        Person person2 = new Person("Bob", 30);
        
        // 訪問屬性和方法
        person1.Introduce();
        Console.WriteLine($"Is adult: {person1.IsAdult}");
        
        // 訪問靜態成員
        Console.WriteLine($"Total people created: {Person.TotalPeople}");
        Person.DisplaySpecies();
        
        // 對象初始化器 (C# 3.0+)
        Person person3 = new Person
        {
            Name = "Charlie",
            Age = 35,
            Address = "123 Main St"
        };
        
        // 使用 with 表達式創建副本 (C# 9.0+ 需要記錄類型)
        // var person4 = person3 with { Age = 36 };
    }
}

繼承和多態

csharp

// 基類
public class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    public Animal(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound");
    }
    
    public void Eat()
    {
        Console.WriteLine($"{Name} is eating");
    }
}

// 派生類
public class Dog : Animal
{
    public string Breed { get; set; }
    
    // 使用 base 調用基類構造函數
    public Dog(string name, int age, string breed) 
        : base(name, age)
    {
        Breed = breed;
    }
    
    // 重寫虛方法
    public override void MakeSound()
    {
        Console.WriteLine($"{Name} says: Woof! Woof!");
    }
    
    // 新方法
    public void WagTail()
    {
        Console.WriteLine($"{Name} is wagging its tail");
    }
    
    // 隱藏基類方法 (使用 new 關鍵字)
    public new void Eat()
    {
        Console.WriteLine($"{Name} the dog is eating dog food");
    }
}

// 另一個派生類
public class Cat : Animal
{
    public bool IsIndoor { get; set; }
    
    public Cat(string name, int age, bool isIndoor)
        : base(name, age)
    {
        IsIndoor = isIndoor;
    }
    
    public override void MakeSound()
    {
        Console.WriteLine($"{Name} says: Meow!");
    }
    
    public void Purr()
    {
        Console.WriteLine($"{Name} is purring");
    }
}

// 密封類 (不能被繼承)
public sealed class Lion : Animal
{
    public Lion(string name, int age) : base(name, age) { }
    
    public override void MakeSound()
    {
        Console.WriteLine("Roar!");
    }
}

// 抽象類 (不能實例化)
public abstract class Shape
{
    public abstract double Area { get; }
    public abstract double Perimeter { get; }
    
    // 抽象方法 (必須在派生類中實現)
    public abstract void Draw();
    
    // 具體方法
    public void DisplayInfo()
    {
        Console.WriteLine($"Area: {Area}, Perimeter: {Perimeter}");
    }
    
    // 虛方法
    public virtual void Scale(double factor)
    {
        Console.WriteLine($"Scaling by factor {factor}");
    }
}

// 實現抽象類
public class Circle : Shape
{
    public double Radius { get; set; }
    
    public Circle(double radius)
    {
        Radius = radius;
    }
    
    public override double Area => Math.PI * Radius * Radius;
    
    public override double Perimeter => 2 * Math.PI * Radius;
    
    public override void Draw()
    {
        Console.WriteLine($"Drawing a circle with radius {Radius}");
    }
    
    public override void Scale(double factor)
    {
        Radius *= factor;
        Console.WriteLine($"Circle scaled to radius {Radius}");
    }
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    
    public Rectangle(double width, double height)
    {
        Width = width;
        Height = height;
    }
    
    public override double Area => Width * Height;
    
    public override double Perimeter => 2 * (Width + Height);
    
    public override void Draw()
    {
        Console.WriteLine($"Drawing a rectangle {Width}x{Height}");
    }
}

// 接口
public interface IMovable
{
    void Move();
    void Stop();
    
    // 默認接口方法 (C# 8.0+)
    void Turn()
    {
        Console.WriteLine("Turning...");
    }
    
    // 靜態方法 (C# 8.0+)
    static string GetTypeName() => "IMovable";
}

public interface IFlyable
{
    void Fly();
    int MaxAltitude { get; }
}

// 實現多個接口
public class Bird : Animal, IMovable, IFlyable
{
    public int MaxAltitude { get; } = 1000;
    
    public Bird(string name, int age) : base(name, age) { }
    
    public override void MakeSound()
    {
        Console.WriteLine("Chirp! Chirp!");
    }
    
    public void Move()
    {
        Console.WriteLine($"{Name} is flying");
    }
    
    public void Stop()
    {
        Console.WriteLine($"{Name} has landed");
    }
    
    public void Fly()
    {
        Console.WriteLine($"{Name} is flying at altitude {MaxAltitude}m");
    }
}

// 多態演示
class InheritanceDemo
{
    public static void Demo()
    {
        // 繼承示例
        Dog dog = new Dog("Buddy", 3, "Golden Retriever");
        dog.MakeSound();
        dog.Eat();
        dog.WagTail();
        
        // 多態示例
        Animal myAnimal = new Dog("Max", 2, "Beagle");
        myAnimal.MakeSound();  // 調用 Dog 的 MakeSound
        myAnimal.Eat();         // 調用 Animal 的 Eat
        
        // 使用基類引用
        Animal[] animals = new Animal[3];
        animals[0] = new Dog("Rex", 4, "German Shepherd");
        animals[1] = new Cat("Whiskers", 2, true);
        animals[2] = new Bird("Tweety", 1);
        
        foreach (Animal animal in animals)
        {
            animal.MakeSound();  // 多態調用
            
            // 類型檢查和轉換
            if (animal is Dog d)
            {
                d.WagTail();
            }
            
            if (animal is Cat cat)
            {
                cat.Purr();
            }
        }
        
        // 抽象類示例
        Shape circle = new Circle(5);
        Shape rectangle = new Rectangle(4, 6);
        
        circle.Draw();
        circle.DisplayInfo();
        circle.Scale(2);
        
        rectangle.Draw();
        rectangle.DisplayInfo();
        
        // 接口示例
        IMovable[] movables = new IMovable[2];
        movables[0] = new Bird("Sparrow", 1);
        movables[1] = new Car();
        
        foreach (var movable in movables)
        {
            movable.Move();
            movable.Turn();  // 調用默認接口方法
            movable.Stop();
        }
        
        // 訪問靜態接口方法
        Console.WriteLine($"Interface type: {IMovable.GetTypeName()}");
    }
}

public class Car : IMovable
{
    public void Move()
    {
        Console.WriteLine("Car is moving");
    }
    
    public void Stop()
    {
        Console.WriteLine("Car has stopped");
    }
}

封裝和訪問修飾符

csharp

// 訪問修飾符演示
class AccessModifiersDemo
{
    // public - 無限制訪問
    public int PublicField = 1;
    
    // private - 只能在當前類中訪問
    private int _privateField = 2;
    
    // protected - 當前類和派生類中訪問
    protected int ProtectedField = 3;
    
    // internal - 同一程序集內訪問
    internal int InternalField = 4;
    
    // protected internal - 同一程序集或派生類中訪問
    protected internal int ProtectedInternalField = 5;
    
    // private protected - 同一程序集中的派生類訪問 (C# 7.2+)
    private protected int PrivateProtectedField = 6;
    
    public void TestAccess()
    {
        // 所有字段都可以在類內部訪問
        Console.WriteLine($"Private field: {_privateField}");
    }
}

// 派生類
class DerivedClass : AccessModifiersDemo
{
    public void TestProtectedAccess()
    {
        // 可以訪問 protected, protected internal, private protected 字段
        Console.WriteLine($"Protected field: {ProtectedField}");
        Console.WriteLine($"Protected internal field: {ProtectedInternalField}");
        Console.WriteLine($"Private protected field: {PrivateProtectedField}");
        
        // 不能訪問 private 字段
        // Console.WriteLine(_privateField); // 編譯錯誤
    }
}

// 另一個程序集中的類 (假設)
/*
class ExternalClass
{
    public void Test()
    {
        AccessModifiersDemo demo = new AccessModifiersDemo();
        
        // 只能訪問 public 和 internal 字段
        Console.WriteLine(demo.PublicField);
        Console.WriteLine(demo.InternalField);
        
        // 不能訪問 protected, private, protected internal
        // Console.WriteLine(demo.ProtectedField); // 編譯錯誤
    }
}
*/

// 封裝示例
public class BankAccount
{
    // 私有字段 - 封裝數據
    private decimal _balance;
    private string _accountNumber;
    private string _ownerName;
    private List<Transaction> _transactions;
    
    // 公共屬性 - 提供受控訪問
    public decimal Balance 
    { 
        get => _balance; 
        private set => _balance = value;  // 只能在類內部設置
    }
    
    public string AccountNumber 
    { 
        get => _accountNumber; 
        private set => _accountNumber = value; 
    }
    
    public string OwnerName 
    { 
        get => _ownerName; 
        set 
        {
            if (!string.IsNullOrWhiteSpace(value))
                _ownerName = value;
        }
    }
    
    // 只讀屬性
    public IReadOnlyList<Transaction> Transactions => _transactions.AsReadOnly();
    
    // 構造函數
    public BankAccount(string accountNumber, string ownerName, decimal initialBalance = 0)
    {
        AccountNumber = accountNumber;
        OwnerName = ownerName;
        _balance = initialBalance;
        _transactions = new List<Transaction>();
        
        if (initialBalance > 0)
        {
            _transactions.Add(new Transaction("Initial deposit", initialBalance));
        }
    }
    
    // 公共方法 - 提供功能
    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Deposit amount must be positive");
        
        _balance += amount;
        _transactions.Add(new Transaction("Deposit", amount));
        Console.WriteLine($"Deposited {amount:C}. New balance: {_balance:C}");
    }
    
    public bool Withdraw(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Withdrawal amount must be positive");
        
        if (amount > _balance)
        {
            Console.WriteLine("Insufficient funds");
            return false;
        }
        
        _balance -= amount;
        _transactions.Add(new Transaction("Withdrawal", -amount));
        Console.WriteLine($"Withdrew {amount:C}. New balance: {_balance:C}");
        return true;
    }
    
    public void Transfer(BankAccount recipient, decimal amount)
    {
        if (Withdraw(amount))
        {
            recipient.Deposit(amount);
            _transactions.Add(new Transaction($"Transfer to {recipient.AccountNumber}", -amount));
        }
    }
    
    public void PrintStatement()
    {
        Console.WriteLine($"Account Statement for {AccountNumber}");
        Console.WriteLine($"Owner: {OwnerName}");
        Console.WriteLine($"Balance: {_balance:C}");
        Console.WriteLine("\nTransactions:");
        
        foreach (var transaction in _transactions)
        {
            Console.WriteLine($"{transaction.Date:yyyy-MM-dd}: {transaction.Description} {transaction.Amount:C}");
        }
    }
    
    // 私有方法 - 內部實現細節
    private void ValidateAmount(decimal amount)
    {
        if (amount < 0)
            throw new ArgumentException("Amount cannot be negative");
    }
}

public class Transaction
{
    public DateTime Date { get; }
    public string Description { get; }
    public decimal Amount { get; }
    
    public Transaction(string description, decimal amount)
    {
        Date = DateTime.Now;
        Description = description;
        Amount = amount;
    }
}

結構體與枚舉

csharp

// 枚舉定義
public enum DayOfWeek
{
    Sunday,     // 0
    Monday,     // 1
    Tuesday,    // 2
    Wednesday,  // 3
    Thursday,   // 4
    Friday,     // 5
    Saturday    // 6
}

// 指定值的枚舉
public enum HttpStatusCode
{
    OK = 200,
    Created = 201,
    BadRequest = 400,
    Unauthorized = 401,
    NotFound = 404,
    InternalServerError = 500
}

// 標誌枚舉 (用於位操作)
[Flags]
public enum FilePermissions
{
    None = 0,           // 0
    Read = 1,           // 1 << 0
    Write = 2,          // 1 << 1
    Execute = 4,        // 1 << 2
    ReadWrite = Read | Write,  // 3
    All = Read | Write | Execute  // 7
}

// 結構體 - 值類型
public struct Point
{
    // 字段
    public int X;
    public int Y;
    
    // 屬性
    public double Magnitude => Math.Sqrt(X * X + Y * Y);
    
    // 構造函數
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    // 方法
    public void Translate(int dx, int dy)
    {
        X += dx;
        Y += dy;
    }
    
    // 重寫 ToString
    public override string ToString() => $"({X}, {Y})";
    
    // 運算符重載
    public static Point operator +(Point a, Point b)
    {
        return new Point(a.X + b.X, a.Y + b.Y);
    }
    
    public static Point operator -(Point a, Point b)
    {
        return new Point(a.X - b.X, a.Y - b.Y);
    }
    
    public static bool operator ==(Point a, Point b)
    {
        return a.X == b.X && a.Y == b.Y;
    }
    
    public static bool operator !=(Point a, Point b)
    {
        return !(a == b);
    }
    
    // 重寫 Equals 和 GetHashCode
    public override bool Equals(object obj)
    {
        return obj is Point point && this == point;
    }
    
    public override int GetHashCode()
    {
        return HashCode.Combine(X, Y);
    }
}

// 只讀結構 (C# 7.2+)
public readonly struct ReadOnlyPoint
{
    public int X { get; }
    public int Y { get; }
    
    public ReadOnlyPoint(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    // 所有字段都必須在構造函數中初始化
    // 不允許有非只讀的屬性或字段
}

// ref 結構 (C# 7.2+)
public ref struct RefPoint
{
    public int X;
    public int Y;
    
    public RefPoint(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    // ref 結構不能實現接口或放在堆上
}

// 使用示例
class StructEnumDemo
{
    public static void Demo()
    {
        // 枚舉使用
        DayOfWeek today = DayOfWeek.Monday;
        Console.WriteLine($"Today is {today} (value: {(int)today})");
        
        // 枚舉轉換
        string dayString = "Friday";
        if (Enum.TryParse(dayString, out DayOfWeek parsedDay))
        {
            Console.WriteLine($"Parsed day: {parsedDay}");
        }
        
        // 標誌枚舉
        FilePermissions permissions = FilePermissions.Read | FilePermissions.Write;
        Console.WriteLine($"Permissions: {permissions}");
        
        // 檢查標誌
        if (permissions.HasFlag(FilePermissions.Read))
        {
            Console.WriteLine("Has read permission");
        }
        
        // 結構體使用
        Point p1 = new Point(10, 20);
        Point p2 = new Point(5, 15);
        
        // 運算符重載
        Point sum = p1 + p2;
        Console.WriteLine($"p1 + p2 = {sum}");
        
        // 結構體是值類型
        Point p3 = p1;  // 複製值
        p3.X = 100;
        Console.WriteLine($"p1.X = {p1.X}, p3.X = {p3.X}"); // 不同
        
        // 比較
        Console.WriteLine($"p1 == p2: {p1 == p2}");
        
        // 使用 with 表達式創建修改的副本 (C# 9.0+ 用於結構體)
        Point p4 = p1 with { X = 50 };
        Console.WriteLine($"Modified copy: {p4}");
        
        // 枚舉所有值
        Console.WriteLine("\nAll days of week:");
        foreach (DayOfWeek day in Enum.GetValues(typeof(DayOfWeek)))
        {
            Console.WriteLine($"{day} = {(int)day}");
        }
        
        // 枚舉特性
        var attributes = typeof(HttpStatusCode).GetCustomAttributes(false);
        Console.WriteLine($"\nEnum type: {typeof(HttpStatusCode).Name}");
    }
}

高級特性與委託

委託和事件

csharp

// 委託定義
public delegate void SimpleDelegate();
public delegate int CalculatorDelegate(int a, int b);
public delegate TResult GenericDelegate<T, TResult>(T arg);
public delegate void EventHandlerDelegate(object sender, EventArgs e);

// 自定義事件參數
public class TemperatureChangedEventArgs : EventArgs
{
    public double OldTemperature { get; }
    public double NewTemperature { get; }
    public DateTime ChangeTime { get; }
    
    public TemperatureChangedEventArgs(double oldTemp, double newTemp)
    {
        OldTemperature = oldTemp;
        NewTemperature = newTemp;
        ChangeTime = DateTime.Now;
    }
}

// 事件發布者
public class Thermostat
{
    private double _temperature;
    
    // 定義事件 (使用 EventHandler 委託)
    public event EventHandler<TemperatureChangedEventArgs> TemperatureChanged;
    
    // 定義事件 (自定義委託)
    public event EventHandlerDelegate OnTemperatureChanged;
    
    public double Temperature
    {
        get => _temperature;
        set
        {
            if (_temperature != value)
            {
                double oldTemp = _temperature;
                _temperature = value;
                
                // 觸發事件
                OnTemperatureChanged?.Invoke(this, EventArgs.Empty);
                TemperatureChanged?.Invoke(this, 
                    new TemperatureChangedEventArgs(oldTemp, value));
            }
        }
    }
}

// 事件訂閱者
public class TemperatureDisplay
{
    public void Subscribe(Thermostat thermostat)
    {
        thermostat.TemperatureChanged += OnTemperatureChanged;
    }
    
    private void OnTemperatureChanged(object sender, TemperatureChangedEventArgs e)
    {
        Console.WriteLine($"Temperature changed from {e.OldTemperature}°C " +
                         $"to {e.NewTemperature}°C at {e.ChangeTime:HH:mm:ss}");
    }
}

// 使用委託的類
public class MathOperations
{
    public static int Add(int a, int b) => a + b;
    public static int Subtract(int a, int b) => a - b;
    public static int Multiply(int a, int b) => a * b;
    public int Divide(int a, int b) => b != 0 ? a / b : 0;
}

// 委託和事件演示
class DelegateEventDemo
{
    public static void Demo()
    {
        // 委託實例化
        CalculatorDelegate addDelegate = MathOperations.Add;
        CalculatorDelegate subtractDelegate = MathOperations.Subtract;
        
        // 調用委託
        int result = addDelegate(10, 5);
        Console.WriteLine($"10 + 5 = {result}");
        
        // 多播委託
        CalculatorDelegate multiDelegate = addDelegate;
        multiDelegate += subtractDelegate;
        multiDelegate += MathOperations.Multiply;
        
        // 多播委託調用所有方法,但只返回最後一個結果
        int multiResult = multiDelegate(10, 5);
        Console.WriteLine($"Multi-delegate result (last): {multiResult}");
        
        // 獲取所有調用結果
        Delegate[] delegates = multiDelegate.GetInvocationList();
        foreach (CalculatorDelegate del in delegates)
        {
            Console.WriteLine($"Result: {del(10, 5)}");
        }
        
        // 匿名方法 (C# 2.0+)
        CalculatorDelegate powerDelegate = delegate(int a, int b)
        {
            return (int)Math.Pow(a, b);
        };
        Console.WriteLine($"2^3 = {powerDelegate(2, 3)}");
        
        // Lambda 表達式 (C# 3.0+)
        CalculatorDelegate maxDelegate = (a, b) => a > b ? a : b;
        CalculatorDelegate minDelegate = (a, b) =>
        {
            return a < b ? a : b;
        };
        
        // 泛型委託
        GenericDelegate<string, int> stringLength = s => s.Length;
        Console.WriteLine($"Length of 'Hello': {stringLength("Hello")}");
        
        // 內置委託類型
        Func<int, int, int> funcAdd = (a, b) => a + b;
        Action<string> actionPrint = message => Console.WriteLine(message);
        Predicate<int> isEven = n => n % 2 == 0;
        
        Console.WriteLine($"Is 4 even? {isEven(4)}");
        
        // 事件演示
        Thermostat thermostat = new Thermostat();
        TemperatureDisplay display = new TemperatureDisplay();
        
        display.Subscribe(thermostat);
        
        // 使用 Lambda 訂閱事件
        thermostat.TemperatureChanged += (sender, e) =>
        {
            Console.WriteLine($"Lambda handler: Temp changed to {e.NewTemperature}°C");
        };
        
        // 觸發事件
        thermostat.Temperature = 20.5;
        thermostat.Temperature = 22.0;
        
        // 取消訂閱
        thermostat.TemperatureChanged -= display.OnTemperatureChanged;
        
        // 事件訪問器
        EventDemo eventDemo = new EventDemo();
        eventDemo.MyEvent += () => Console.WriteLine("Event fired");
        eventDemo.RaiseEvent();
    }
}

// 自定義事件訪問器
public class EventDemo
{
    private EventHandlerDelegate _myEvent;
    
    public event EventHandlerDelegate MyEvent
    {
        add
        {
            Console.WriteLine("Adding event handler");
            _myEvent += value;
        }
        remove
        {
            Console.WriteLine("Removing event handler");
            _myEvent -= value;
        }
    }
    
    public void RaiseEvent()
    {
        _myEvent?.Invoke(this, EventArgs.Empty);
    }
}

匿名類型和動態類型

csharp

class AnonymousDynamicDemo
{
    public static void Demo()
    {
        // 匿名類型 (C# 3.0+)
        var person = new 
        { 
            Name = "John", 
            Age = 30,
            Address = new { City = "New York", ZipCode = "10001" }
        };
        
        Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
        Console.WriteLine($"City: {person.Address.City}");
        
        // 匿名類型是不可變的
        // person.Name = "Jane"; // 編譯錯誤
        
        // 匿名類型在 LINQ 中很有用
        var people = new[]
        {
            new { Name = "Alice", Age = 25 },
            new { Name = "Bob", Age = 30 },
            new { Name = "Charlie", Age = 35 }
        };
        
        var youngPeople = people.Where(p => p.Age < 30)
                                .Select(p => new { p.Name, IsYoung = true });
        
        foreach (var p in youngPeople)
        {
            Console.WriteLine($"{p.Name} is young: {p.IsYoung}");
        }
        
        // 動態類型 (C# 4.0+)
        dynamic dynamicVariable = 10;
        Console.WriteLine($"Type: {dynamicVariable.GetType()}, Value: {dynamicVariable}");
        
        dynamicVariable = "Now I'm a string";
        Console.WriteLine($"Type: {dynamicVariable.GetType()}, Value: {dynamicVariable}");
        
        dynamicVariable = new { Property = "Value" };
        Console.WriteLine($"Property: {dynamicVariable.Property}");
        
        // 動態調用方法
        dynamic math = new MathDynamic();
        int sum = math.Add(5, 3);
        Console.WriteLine($"Dynamic add: 5 + 3 = {sum}");
        
        // 嘗試調用不存在的方法
        try
        {
            math.NonExistentMethod();
        }
        catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
        {
            Console.WriteLine($"Runtime error: {ex.Message}");
        }
        
        // ExpandoObject (動態對象)
        dynamic expando = new System.Dynamic.ExpandoObject();
        expando.Name = "Dynamic Object";
        expando.Value = 42;
        expando.Print = (Action)(() => 
        {
            Console.WriteLine($"Name: {expando.Name}, Value: {expando.Value}");
        });
        
        expando.Print();
        
        // 動態對象作為字典
        var dict = (IDictionary<string, object>)expando;
        dict["NewProperty"] = "Added dynamically";
        Console.WriteLine($"New property: {expando.NewProperty}");
        
        // 與反射比較
        object obj = new Person("Test", 20);
        var type = obj.GetType();
        var nameProperty = type.GetProperty("Name");
        string name = (string)nameProperty.GetValue(obj);
        
        // 使用動態更簡單
        dynamic dynObj = obj;
        string dynName = dynObj.Name;
    }
}

public class MathDynamic
{
    public int Add(int a, int b) => a + b;
    public int Multiply(int a, int b) => a * b;
}

擴展方法

csharp

// 擴展方法必須在靜態類中定義
public static class StringExtensions
{
    // 擴展 string 類型
    public static bool IsNullOrEmpty(this string str)
    {
        return string.IsNullOrEmpty(str);
    }
    
    public static bool IsNullOrWhiteSpace(this string str)
    {
        return string.IsNullOrWhiteSpace(str);
    }
    
    public static string Reverse(this string str)
    {
        if (string.IsNullOrEmpty(str))
            return str;
            
        char[] charArray = str.ToCharArray();
        Array.Reverse(charArray);
        return new string(charArray);
    }
    
    public static string Truncate(this string str, int maxLength)
    {
        if (string.IsNullOrEmpty(str) || str.Length <= maxLength)
            return str;
            
        return str.Substring(0, maxLength) + "...";
    }
    
    public static bool IsPalindrome(this string str)
    {
        if (string.IsNullOrEmpty(str))
            return false;
            
        string clean = new string(str.Where(char.IsLetterOrDigit).ToArray())
                          .ToLower();
        return clean == clean.Reverse();
    }
    
    // 為 IEnumerable<T> 擴展
    public static string Join<T>(this IEnumerable<T> items, string separator)
    {
        return string.Join(separator, items);
    }
}

// 為自定義類型添加擴展
public static class PersonExtensions
{
    public static string GetFullInfo(this Person person)
    {
        return $"{person.Name}, {person.Age} years old";
    }
    
    public static bool IsTeenager(this Person person)
    {
        return person.Age >= 13 && person.Age <= 19;
    }
}

// 為接口添加擴展
public static class CollectionExtensions
{
    public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            collection.Add(item);
        }
    }
    
    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach (var item in collection)
        {
            action(item);
        }
    }
}

// 擴展方法演示
class ExtensionMethodDemo
{
    public static void Demo()
    {
        // 使用字符串擴展方法
        string text = "Hello World";
        
        Console.WriteLine($"Original: {text}");
        Console.WriteLine($"Reversed: {text.Reverse()}");
        Console.WriteLine($"Truncated (5): {text.Truncate(5)}");
        Console.WriteLine($"Is palindrome? {text.IsPalindrome()}");
        Console.WriteLine($"Is 'racecar' palindrome? {"racecar".IsPalindrome()}");
        
        // 使用集合擴展方法
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        
        Console.WriteLine($"\nNumbers: {numbers.Join(", ")}");
        
        numbers.ForEach(n => Console.WriteLine($"Number: {n}"));
        
        // 添加多個項目
        numbers.AddRange(new[] { 6, 7, 8 });
        Console.WriteLine($"After AddRange: {numbers.Join(", ")}");
        
        // 使用自定義類型擴展
        Person person = new Person("Alice", 25);
        Console.WriteLine($"\nPerson info: {person.GetFullInfo()}");
        Console.WriteLine($"Is teenager? {person.IsTeenager()}");
        
        // LINQ 本身就是擴展方法
        var squares = numbers.Select(n => n * n);
        Console.WriteLine($"Squares: {squares.Join(", ")}");
        
        // 鏈式調用擴展方法
        string result = numbers.Where(n => n % 2 == 0)
                              .Select(n => n.ToString())
                              .Join("|");
        Console.WriteLine($"Even numbers: {result}");
        
        // 為值類型添加擴展
        int value = 42;
        Console.WriteLine($"\nIs 42 even? {value.IsEven()}");
        Console.WriteLine($"Square of 5: {5.Square()}");
    }
}

// 值類型擴展
public static class IntExtensions
{
    public static bool IsEven(this int number) => number % 2 == 0;
    public static bool IsOdd(this int number) => !number.IsEven();
    public static int Square(this int number) => number * number;
    public static int Cube(this int number) => number * number * number;
    public static int Factorial(this int number)
    {
        if (number <= 1) return 1;
        return number * Factorial(number - 1);
    }
    
    public static string ToOrdinal(this int number)
    {
        if (number <= 0) return number.ToString();
        
        switch (number % 100)
        {
            case 11:
            case 12:
            case 13:
                return number + "th";
        }
        
        return (number % 10) switch
        {
            1 => number + "st",
            2 => number + "nd",
            3 => number + "rd",
            _ => number + "th"
        };
    }
}

泛型與集合

泛型基礎

csharp

// 泛型類
public class GenericStack<T>
{
    private T[] _items;
    private int _top;
    
    public GenericStack(int capacity = 10)
    {
        _items = new T[capacity];
        _top = -1;
    }
    
    public void Push(T item)
    {
        if (_top == _items.Length - 1)
        {
            Array.Resize(ref _items, _items.Length * 2);
        }
        
        _items[++_top] = item;
    }
    
    public T Pop()
    {
        if (_top == -1)
            throw new InvalidOperationException("Stack is empty");
            
        return _items[_top--];
    }
    
    public T Peek()
    {
        if (_top == -1)
            throw new InvalidOperationException("Stack is empty");
            
        return _items[_top];
    }
    
    public bool IsEmpty => _top == -1;
    public int Count => _top + 1;
    
    // 泛型方法
    public void ProcessItems<U>(U processor) where U : IItemProcessor<T>
    {
        for (int i = 0; i <= _top; i++)
        {
            processor.Process(_items[i]);
        }
    }
}

// 泛型接口
public interface IRepository<T> where T : class
{
    void Add(T entity);
    void Remove(T entity);
    T GetById(int id);
    IEnumerable<T> GetAll();
}

// 泛型約束
public class GenericRepository<T> : IRepository<T> where T : class, new()
{
    private List<T> _items = new List<T>();
    
    public void Add(T entity)
    {
        _items.Add(entity);
    }
    
    public void Remove(T entity)
    {
        _items.Remove(entity);
    }
    
    public T GetById(int id)
    {
        // 實際實現會根據 ID 查找
        return _items.FirstOrDefault();
    }
    
    public IEnumerable<T> GetAll()
    {
        return _items;
    }
    
    // 創建新實例
    public T Create()
    {
        return new T();
    }
}

// 多個類型參數
public class KeyValuePair<K, V>
{
    public K Key { get; set; }
    public V Value { get; set; }
    
    public KeyValuePair(K key, V value)
    {
        Key = key;
        Value = value;
    }
}

// 協變接口 (out)
public interface IReadOnlyRepository<out T> where T : class
{
    T GetById(int id);
    IEnumerable<T> GetAll();
}

// 逆變接口 (in)
public interface IComparator<in T>
{
    int Compare(T x, T y);
}

// 泛型委託
public delegate T Transformer<T>(T input);

// 泛型演示
class GenericDemo
{
    public static void Demo()
    {
        // 使用泛型類
        GenericStack<int> intStack = new GenericStack<int>();
        intStack.Push(1);
        intStack.Push(2);
        intStack.Push(3);
        
        Console.WriteLine($"Stack count: {intStack.Count}");
        Console.WriteLine($"Top item: {intStack.Peek()}");
        Console.WriteLine($"Popped: {intStack.Pop()}");
        
        GenericStack<string> stringStack = new GenericStack<string>();
        stringStack.Push("Hello");
        stringStack.Push("World");
        
        // 泛型方法
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        List<string> strings = numbers.ConvertAll(n => n.ToString());
        
        Console.WriteLine($"Converted strings: {string.Join(", ", strings)}");
        
        // 泛型約束示例
        GenericRepository<Person> personRepo = new GenericRepository<Person>();
        personRepo.Add(new Person("Alice", 25));
        
        // 創建新實例
        Person newPerson = personRepo.Create();
        newPerson.Name = "Bob";
        newPerson.Age = 30;
        personRepo.Add(newPerson);
        
        // 泛型字典
        Dictionary<string, Person> phoneBook = new Dictionary<string, Person>
        {
            ["555-1234"] = new Person("John", 30),
            ["555-5678"] = new Person("Jane", 25)
        };
        
        // 添加和訪問
        phoneBook["555-9999"] = new Person("Bob", 35);
        
        if (phoneBook.TryGetValue("555-1234", out Person person))
        {
            Console.WriteLine($"Found: {person.Name}");
        }
        
        // 遍歷字典
        foreach (var kvp in phoneBook)
        {
            Console.WriteLine($"{kvp.Key}: {kvp.Value.Name}");
        }
        
        // 使用默認值
        T GetDefault<T>() => default;
        
        Console.WriteLine($"Default int: {GetDefault<int>()}");
        Console.WriteLine($"Default string: {GetDefault<string>() ?? "null"}");
        
        // 類型推斷
        var pair = CreatePair("key", 123);
        Console.WriteLine($"Pair: {pair.Key} = {pair.Value}");
        
        // 泛型與繼承
        NumericCalculator<int> intCalc = new NumericCalculator<int>();
        Console.WriteLine($"Sum: {intCalc.Add(5, 3)}");
    }
    
    // 泛型方法
    public static KeyValuePair<K, V> CreatePair<K, V>(K key, V value)
    {
        return new KeyValuePair<K, V>(key, value);
    }
    
    // 泛型與運算符
    public static T Add<T>(T a, T b) where T : IAddable<T>
    {
        return a.Add(b);
    }
}

// 用於演示的接口
public interface IItemProcessor<T>
{
    void Process(T item);
}

// 用於約束的示例
public interface IAddable<T>
{
    T Add(T other);
}

public class NumericCalculator<T> where T : IAddable<T>
{
    public T Add(T a, T b) => a.Add(b);
}

集合框架

csharp

class CollectionsDemo
{
    public static void Demo()
    {
        Console.WriteLine("=== List<T> ===");
        // List<T> - 動態數組
        List<string> fruits = new List<string> { "Apple", "Banana" };
        fruits.Add("Cherry");
        fruits.AddRange(new[] { "Date", "Elderberry" });
        
        fruits.Insert(1, "Apricot");
        fruits.Remove("Banana");
        fruits.RemoveAt(0);
        
        Console.WriteLine($"Count: {fruits.Count}");
        Console.WriteLine($"Capacity: {fruits.Capacity}");
        Console.WriteLine($"Contains 'Cherry': {fruits.Contains("Cherry")}");
        Console.WriteLine($"Index of 'Date': {fruits.IndexOf("Date")}");
        
        fruits.ForEach(f => Console.WriteLine($"- {f}"));
        
        // 排序
        List<int> numbers = new List<int> { 5, 2, 8, 1, 9 };
        numbers.Sort();
        Console.WriteLine($"Sorted: {string.Join(", ", numbers)}");
        
        // 自定義排序
        List<Person> people = new List<Person>
        {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        };
        
        people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
        
        Console.WriteLine("\n=== Dictionary<TKey, TValue> ===");
        // Dictionary<TKey, TValue> - 哈希表
        Dictionary<string, int> wordCount = new Dictionary<string, int>
        {
            ["hello"] = 1,
            ["world"] = 2
        };
        
        wordCount.Add("csharp", 3);
        wordCount["dotnet"] = 4;
        
        // 安全的訪問方式
        if (wordCount.TryGetValue("hello", out int count))
        {
            Console.WriteLine($"'hello' count: {count}");
        }
        
        // 遍歷
        foreach (var kvp in wordCount)
        {
            Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }
        
        // Keys 和 Values 集合
        Console.WriteLine($"Keys: {string.Join(", ", wordCount.Keys)}");
        Console.WriteLine($"Values: {string.Join(", ", wordCount.Values)}");
        
        Console.WriteLine("\n=== HashSet<T> ===");
        // HashSet<T> - 不重複的集合
        HashSet<int> set1 = new HashSet<int> { 1, 2, 3, 4, 5 };
        HashSet<int> set2 = new HashSet<int> { 4, 5, 6, 7, 8 };
        
        set1.Add(6); // 添加已存在的元素會被忽略
        Console.WriteLine($"Set1: {string.Join(", ", set1)}");
        
        // 集合運算
        var union = new HashSet<int>(set1);
        union.UnionWith(set2);
        Console.WriteLine($"Union: {string.Join(", ", union)}");
        
        var intersection = new HashSet<int>(set1);
        intersection.IntersectWith(set2);
        Console.WriteLine($"Intersection: {string.Join(", ", intersection)}");
        
        var except = new HashSet<int>(set1);
        except.ExceptWith(set2);
        Console.WriteLine($"Except: {string.Join(", ", except)}");
        
        var symmetricExcept = new HashSet<int>(set1);
        symmetricExcept.SymmetricExceptWith(set2);
        Console.WriteLine($"Symmetric Except: {string.Join(", ", symmetricExcept)}");
        
        Console.WriteLine("\n=== Queue<T> ===");
        // Queue<T> - 先進先出
        Queue<string> queue = new Queue<string>();
        queue.Enqueue("First");
        queue.Enqueue("Second");
        queue.Enqueue("Third");
        
        Console.WriteLine($"Count: {queue.Count}");
        Console.WriteLine($"Peek: {queue.Peek()}");
        
        while (queue.Count > 0)
        {
            Console.WriteLine($"Dequeued: {queue.Dequeue()}");
        }
        
        Console.WriteLine("\n=== Stack<T> ===");
        // Stack<T> - 後進先出
        Stack<string> stack = new Stack<string>();
        stack.Push("First");
        stack.Push("Second");
        stack.Push("Third");
        
        Console.WriteLine($"Count: {stack.Count}");
        Console.WriteLine($"Peek: {stack.Peek()}");
        
        while (stack.Count > 0)
        {
            Console.WriteLine($"Popped: {stack.Pop()}");
        }
        
        Console.WriteLine("\n=== LinkedList<T> ===");
        // LinkedList<T> - 雙向鏈表
        LinkedList<string> linkedList = new LinkedList<string>();
        linkedList.AddLast("First");
        linkedList.AddLast("Third");
        
        LinkedListNode<string> node = linkedList.Find("Third");
        if (node != null)
        {
            linkedList.AddBefore(node, "Second");
        }
        
        foreach (var item in linkedList)
        {
            Console.WriteLine($"Item: {item}");
        }
        
        // 遍歷節點
        for (var currentNode = linkedList.First; 
             currentNode != null; 
             currentNode = currentNode.Next)
        {
            Console.WriteLine($"Node: {currentNode.Value}");
        }
        
        Console.WriteLine("\n=== Sorted Collections ===");
        // SortedSet<T>
        SortedSet<int> sortedSet = new SortedSet<int> { 5, 2, 8, 1, 9 };
        Console.WriteLine($"SortedSet: {string.Join(", ", sortedSet)}");
        Console.WriteLine($"Min: {sortedSet.Min}, Max: {sortedSet.Max}");
        
        // SortedDictionary<TKey, TValue>
        SortedDictionary<string, int> sortedDict = new SortedDictionary<string, int>
        {
            ["zebra"] = 1,
            ["apple"] = 2,
            ["banana"] = 3
        };
        
        foreach (var kvp in sortedDict)
        {
            Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }
        
        Console.WriteLine("\n=== Concurrent Collections ===");
        // 線程安全集合
        var concurrentBag = new System.Collections.Concurrent.ConcurrentBag<int>();
        var concurrentDict = new System.Collections.Concurrent.ConcurrentDictionary<string, int>();
        var blockingCollection = new System.Collections.Concurrent.BlockingCollection<int>();
        
        Console.WriteLine("\n=== ReadOnly Collections ===");
        // 只讀視圖
        List<int> originalList = new List<int> { 1, 2, 3, 4, 5 };
        IReadOnlyList<int> readOnlyList = originalList.AsReadOnly();
        
        // readOnlyList[0] = 10; // 編譯錯誤
        originalList[0] = 10; // 這會影響 readOnlyList
        
        Console.WriteLine($"ReadOnly list first item: {readOnlyList[0]}");
        
        // 不可變集合 (需要 System.Collections.Immutable 包)
        /*
        var immutableList = System.Collections.Immutable.ImmutableList.Create(1, 2, 3);
        var newList = immutableList.Add(4); // 返回新列表
        */
    }
}

LINQ 查詢

LINQ 基礎

csharp

class LinqDemo
{
    public static void Demo()
    {
        // 數據源
        List<Person> people = new List<Person>
        {
            new Person("Alice", 25),
            new Person("Bob", 30),
            new Person("Charlie", 35),
            new Person("David", 20),
            new Person("Eve", 28),
            new Person("Frank", 40)
        };
        
        List<Employee> employees = new List<Employee>
        {
            new Employee("Alice", "IT", 50000),
            new Employee("Bob", "HR", 45000),
            new Employee("Charlie", "IT", 60000),
            new Employee("David", "Sales", 40000),
            new Employee("Eve", "IT", 55000)
        };
        
        int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        Console.WriteLine("=== LINQ 查詢語法 ===");
        
        // 查詢語法 (類似 SQL)
        var query1 = from p in people
                     where p.Age > 25
                     orderby p.Name
                     select new { p.Name, p.Age };
        
        foreach (var item in query1)
        {
            Console.WriteLine($"{item.Name}, {item.Age}");
        }
        
        Console.WriteLine("\n=== LINQ 方法語法 ===");
        
        // 方法語法 (擴展方法)
        var query2 = people
            .Where(p => p.Age > 25)
            .OrderBy(p => p.Name)
            .Select(p => new { p.Name, p.Age });
        
        foreach (var item in query2)
        {
            Console.WriteLine($"{item.Name}, {item.Age}");
        }
        
        Console.WriteLine("\n=== 過濾 (Where) ===");
        var adults = people.Where(p => p.Age >= 18);
        var evenNumbers = numbers.Where(n => n % 2 == 0);
        
        Console.WriteLine($"Adults: {adults.Count()} people");
        Console.WriteLine($"Even numbers: {string.Join(", ", evenNumbers)}");
        
        // 多個條件
        var filtered = people.Where(p => p.Age > 20 && p.Name.StartsWith("A"));
        
        Console.WriteLine("\n=== 投影 (Select) ===");
        var names = people.Select(p => p.Name);
        var nameLengths = people.Select(p => new { p.Name, Length = p.Name.Length });
        
        foreach (var item in nameLengths)
        {
            Console.WriteLine($"{item.Name}: {item.Length} chars");
        }
        
        // SelectMany - 展平嵌套集合
        var departments = new List<Department>
        {
            new Department("IT", new[] { "Alice", "Bob" }),
            new Department("HR", new[] { "Charlie", "David" })
        };
        
        var allEmployees = departments.SelectMany(d => d.Employees);
        Console.WriteLine($"All employees: {string.Join(", ", allEmployees)}");
        
        Console.WriteLine("\n=== 排序 (OrderBy) ===");
        var sortedByName = people.OrderBy(p => p.Name);
        var sortedByAgeDesc = people.OrderByDescending(p => p.Age);
        var multiSorted = people.OrderBy(p => p.Name).ThenBy(p => p.Age);
        
        Console.WriteLine("Sorted by name:");
        foreach (var p in sortedByName)
        {
            Console.WriteLine($"  {p.Name} ({p.Age})");
        }
        
        Console.WriteLine("\n=== 分組 (GroupBy) ===");
        var groupedByFirstLetter = people.GroupBy(p => p.Name[0]);
        
        foreach (var group in groupedByFirstLetter)
        {
            Console.WriteLine($"Group '{group.Key}':");
            foreach (var person in group)
            {
                Console.WriteLine($"  {person.Name}");
            }
        }
        
        // 按年齡範圍分組
        var ageGroups = people.GroupBy(p => p.Age / 10 * 10);
        foreach (var group in ageGroups.OrderBy(g => g.Key))
        {
            Console.WriteLine($"Age {group.Key}-{group.Key + 9}: {group.Count()} people");
        }
        
        Console.WriteLine("\n=== 連接 (Join) ===");
        var joinQuery = from p in people
                        join e in employees on p.Name equals e.Name
                        select new { p.Name, p.Age, e.Department, e.Salary };
        
        foreach (var item in joinQuery)
        {
            Console.WriteLine($"{item.Name} ({item.Age}): {item.Department}, ${item.Salary}");
        }
        
        // 左外連接
        var leftJoin = from p in people
                       join e in employees on p.Name equals e.Name into temp
                       from e in temp.DefaultIfEmpty()
                       select new 
                       { 
                           p.Name, 
                           Department = e?.Department ?? "No Department",
                           Salary = e?.Salary ?? 0
                       };
        
        Console.WriteLine("\n=== 分組連接 (GroupJoin) ===");
        var groupJoin = from d in departments
                        join e in employees on d.Name equals e.Department into deptEmployees
                        select new { Department = d.Name, Employees = deptEmployees };
        
        foreach (var dept in groupJoin)
        {
            Console.WriteLine($"{dept.Department}:");
            foreach (var emp in dept.Employees)
            {
                Console.WriteLine($"  {emp.Name}");
            }
        }
        
        Console.WriteLine("\n=== 聚合函數 ===");
        int totalAge = people.Sum(p => p.Age);
        double averageAge = people.Average(p => p.Age);
        int maxAge = people.Max(p => p.Age);
        int minAge = people.Min(p => p.Age);
        int count = people.Count();
        int countAdults = people.Count(p => p.Age >= 18);
        
        Console.WriteLine($"Total age: {totalAge}");
        Console.WriteLine($"Average age: {averageAge:F2}");
        Console.WriteLine($"Max age: {maxAge}");
        Console.WriteLine($"Min age: {minAge}");
        Console.WriteLine($"Total count: {count}");
        Console.WriteLine($"Adults count: {countAdults}");
        
        // Aggregate
        string allNames = people.Aggregate("", (current, next) => 
            current + (current == "" ? "" : ", ") + next.Name);
        Console.WriteLine($"All names: {allNames}");
        
        Console.WriteLine("\n=== 分頁 ===");
        int pageSize = 2;
        int pageNumber = 1;
        
        var paged = people
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize);
        
        Console.WriteLine($"Page {pageNumber}:");
        foreach (var p in paged)
        {
            Console.WriteLine($"  {p.Name}");
        }
        
        Console.WriteLine("\n=== 集合操作 ===");
        List<int> setA = new List<int> { 1, 2, 3, 4, 5 };
        List<int> setB = new List<int> { 4, 5, 6, 7, 8 };
        
        var unionResult = setA.Union(setB);
        var intersectResult = setA.Intersect(setB);
        var exceptResult = setA.Except(setB);
        var distinctNumbers = new[] { 1, 2, 2, 3, 3, 3 }.Distinct();
        
        Console.WriteLine($"Union: {string.Join(", ", unionResult)}");
        Console.WriteLine($"Intersection: {string.Join(", ", intersectResult)}");
        Console.WriteLine($"Except: {string.Join(", ", exceptResult)}");
        Console.WriteLine($"Distinct: {string.Join(", ", distinctNumbers)}");
        
        Console.WriteLine("\n=== 元素操作 ===");
        var first = people.First();
        var firstOrDefault = people.FirstOrDefault(p => p.Age > 100);
        var last = people.Last();
        var single = people.Single(p => p.Name == "Alice");
        var elementAt = people.ElementAt(2);
        
        Console.WriteLine($"First: {first.Name}");
        Console.WriteLine($"First or default (age > 100): {firstOrDefault?.Name ?? "null"}");
        Console.WriteLine($"Last: {last.Name}");
        Console.WriteLine($"Element at index 2: {elementAt.Name}");
        
        Console.WriteLine("\n=== 判斷操作 ===");
        bool anyAdults = people.Any(p => p.Age >= 18);
        bool allAdults = people.All(p => p.Age >= 18);
        bool containsAlice = people.Any(p => p.Name == "Alice");
        
        Console.WriteLine($"Any adults: {anyAdults}");
        Console.WriteLine($"All adults: {allAdults}");
        Console.WriteLine($"Contains Alice: {containsAlice}");
        
        Console.WriteLine("\n=== 轉換操作 ===");
        List<Person> peopleList = people.ToList();
        Person[] peopleArray = people.ToArray();
        Dictionary<string, Person> peopleDict = people.ToDictionary(p => p.Name);
        ILookup<char, Person> lookup = people.ToLookup(p => p.Name[0]);
        
        Console.WriteLine($"List count: {peopleList.Count}");
        Console.WriteLine($"Array length: {peopleArray.Length}");
        Console.WriteLine($"Dictionary count: {peopleDict.Count}");
        
        Console.WriteLine("\n=== 延遲執行 vs 立即執行 ===");
        // 延遲執行
        var deferred = people.Where(p => p.Age > 25);
        people.Add(new Person("Grace", 45)); // 這會影響結果
        
        Console.WriteLine("Deferred execution:");
        foreach (var p in deferred)
        {
            Console.WriteLine($"  {p.Name}");
        }
        
        // 立即執行
        var immediate = people.Where(p => p.Age > 25).ToList();
        people.Add(new Person("Henry", 50)); // 這不會影響結果
        
        Console.WriteLine("Immediate execution:");
        foreach (var p in immediate)
        {
            Console.WriteLine($"  {p.Name}");
        }
        
        Console.WriteLine("\n=== 並行 LINQ (PLINQ) ===");
        var parallelQuery = people.AsParallel()
                                 .Where(p => p.Age > 25)
                                 .OrderBy(p => p.Name);
        
        foreach (var p in parallelQuery)
        {
            Console.WriteLine($"{p.Name} ({p.Age})");
        }
    }
}

// 輔助類
public class Employee
{
    public string Name { get; set; }
    public string Department { get; set; }
    public decimal Salary { get; set; }
    
    public Employee(string name, string department, decimal salary)
    {
        Name = name;
        Department = department;
        Salary = salary;
    }
}

public class Department
{
    public string Name { get; set; }
    public string[] Employees { get; set; }
    
    public Department(string name, string[] employees)
    {
        Name = name;
        Employees = employees;
    }
}

異步編程

async/await

csharp

class AsyncDemo
{
    public static async Task Demo()
    {
        Console.WriteLine("=== 異步編程演示 ===\n");
        
        // 基本異步方法
        await BasicAsyncMethod();
        
        // 返回值的異步方法
        int result = await CalculateAsync(10, 20);
        Console.WriteLine($"計算結果: {result}\n");
        
        // 並行執行多個異步任務
        await MultipleAsyncTasks();
        
        // 異步流 (C# 8.0+)
        await AsyncStreamDemo();
        
        // 異步異常處理
        await AsyncExceptionHandling();
        
        // 取消令牌
        await CancellationTokenDemo();
        
        // 異步與同步的互操作
        SyncOverAsyncWarning();
    }
    
    static async Task BasicAsyncMethod()
    {
        Console.WriteLine("開始異步操作...");
        await Task.Delay(1000); // 模擬耗時操作
        Console.WriteLine("異步操作完成!\n");
    }
    
    static async Task<int> CalculateAsync(int a, int b)
    {
        Console.WriteLine("開始計算...");
        await Task.Delay(500); // 模擬計算時間
        
        // 可以 await 其他異步方法
        int intermediate = await ProcessAsync(a);
        
        return intermediate + b;
    }
    
    static async Task<int> ProcessAsync(int value)
    {
        await Task.Delay(300);
        return value * 2;
    }
    
    static async Task MultipleAsyncTasks()
    {
        Console.WriteLine("開始多個並行任務...");
        
        var task1 = Task.Delay(1000).ContinueWith(_ => "任務1完成");
        var task2 = Task.Delay(800).ContinueWith(_ => "任務2完成");
        var task3 = Task.Delay(1200).ContinueWith(_ => "任務3完成");
        
        // 等待所有任務完成
        var results = await Task.WhenAll(task1, task2, task3);
        Console.WriteLine($"所有任務完成: {string.Join(", ", results)}\n");
        
        // 等待任何一個任務完成
        var tasks = new[]
        {
            Task.Delay(1500).ContinueWith(_ => "慢任務"),
            Task.Delay(500).ContinueWith(_ => "快任務")
        };
        
        var firstResult = await Task.WhenAny(tasks);
        Console.WriteLine($"第一個完成的任務: {await firstResult}\n");
    }
    
    // 異步流 (C# 8.0+)
    static async Task AsyncStreamDemo()
    {
        Console.WriteLine("開始異步流...");
        
        await foreach (var number in GenerateNumbersAsync())
        {
            Console.WriteLine($"收到: {number}");
        }
        Console.WriteLine();
    }
    
    static async IAsyncEnumerable<int> GenerateNumbersAsync()
    {
        for (int i = 1; i <= 5; i++)
        {
            await Task.Delay(200); // 模擬異步操作
            yield return i;
        }
    }
    
    static async Task AsyncExceptionHandling()
    {
        Console.WriteLine("異步異常處理演示...");
        
        try
        {
            await TaskThatThrowsAsync();
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"捕獲到異常: {ex.Message}");
        }
        
        // 多個任務的異常處理
        var task1 = TaskThatThrowsAsync("任務1");
        var task2 = TaskThatThrowsAsync("任務2");
        
        var allTasks = Task.WhenAll(task1, task2);
        
        try
        {
            await allTasks;
        }
        catch
        {
            // 處理 AggregateException
            if (allTasks.Exception != null)
            {
                Console.WriteLine($"總共 {allTasks.Exception.InnerExceptions.Count} 個異常:");
                foreach (var ex in allTasks.Exception.InnerExceptions)
                {
                    Console.WriteLine($"  - {ex.Message}");
                }
            }
        }
        Console.WriteLine();
    }
    
    static async Task TaskThatThrowsAsync(string taskName = "默認任務")
    {
        await Task.Delay(100);
        throw new InvalidOperationException($"{taskName} 拋出異常");
    }
    
    static async Task CancellationTokenDemo()
    {
        Console.WriteLine("取消令牌演示...");
        
        var cts = new CancellationTokenSource();
        cts.CancelAfter(1500); // 1.5秒後自動取消
        
        try
        {
            await LongRunningTaskAsync(cts.Token);
            Console.WriteLine("任務正常完成");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("任務被取消");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"其他異常: {ex.Message}");
        }
        Console.WriteLine();
    }
    
    static async Task LongRunningTaskAsync(CancellationToken cancellationToken)
    {
        for (int i = 0; i < 10; i++)
        {
            cancellationToken.ThrowIfCancellationRequested();
            
            Console.WriteLine($"進度: {i + 1}/10");
            await Task.Delay(500, cancellationToken);
        }
    }
    
    static void SyncOverAsyncWarning()
    {
        Console.WriteLine("=== 同步上下文警告 ===");
        Console.WriteLine("避免在同步方法中調用異步方法時使用 .Result 或 .Wait()");
        Console.WriteLine("這可能導致死鎖!\n");
        
        // 錯誤示例(可能導致死鎖)
        // var result = SomeAsyncMethod().Result;
        
        // 正確做法:使用 async/await 貫穿整個調用鏈
    }
    
    // 異步屬性示例 (C# 8.0+ 不直接支持,但可以通過方法模擬)
    public async Task<string> GetDataAsync()
    {
        await Task.Delay(100);
        return "異步數據";
    }
}

// 異步模式實現
public class AsyncDataLoader
{
    // 傳統的 APM 模式 (Asynchronous Programming Model)
    public IAsyncResult BeginLoadData(AsyncCallback callback, object state)
    {
        var task = LoadDataAsync();
        return task.AsAsyncResult(callback, state);
    }
    
    public string EndLoadData(IAsyncResult asyncResult)
    {
        return ((Task<string>)asyncResult).Result;
    }
    
    // 基於事件的異步模式 (EAP)
    public event EventHandler<DataLoadedEventArgs> DataLoaded;
    
    public void LoadDataAsyncEAP()
    {
        Task.Run(async () =>
        {
            try
            {
                var data = await LoadDataAsync();
                DataLoaded?.Invoke(this, new DataLoadedEventArgs(data));
            }
            catch (Exception ex)
            {
                DataLoaded?.Invoke(this, new DataLoadedEventArgs(null, ex));
            }
        });
    }
    
    // 現代的 TAP 模式 (Task-based Asynchronous Pattern)
    public async Task<string> LoadDataAsync()
    {
        await Task.Delay(1000);
        return "加載的數據";
    }
}

public class DataLoadedEventArgs : EventArgs
{
    public string Data { get; }
    public Exception Error { get; }
    
    public DataLoadedEventArgs(string data, Exception error = null)
    {
        Data = data;
        Error = error;
    }
}

// 異步 Dispose 模式
public class AsyncResource : IAsyncDisposable, IDisposable
{
    private bool _disposed = false;
    
    public async ValueTask DisposeAsync()
    {
        await DisposeAsyncCore();
        Dispose(false);
        GC.SuppressFinalize(this);
    }
    
    protected virtual async ValueTask DisposeAsyncCore()
    {
        // 異步清理資源
        await Task.Delay(100); // 模擬異步清理
        Console.WriteLine("資源已異步清理");
    }
    
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // 同步清理托管資源
            }
            
            // 清理非托管資源
            _disposed = true;
        }
    }
    
    ~AsyncResource()
    {
        Dispose(false);
    }
}

屬性與反射

csharp

// 自定義屬性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | 
               AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public class CustomAttribute : Attribute
{
    public string Description { get; }
    public int Priority { get; set; }
    public string Author { get; set; }
    public DateTime Date { get; set; }
    
    public CustomAttribute(string description)
    {
        Description = description;
        Date = DateTime.Now;
    }
}

// 另一個自定義屬性
[AttributeUsage(AttributeTargets.Property)]
public class ValidationAttribute : Attribute
{
    public int MinLength { get; set; }
    public int MaxLength { get; set; }
    public bool Required { get; set; }
}

// 使用自定義屬性的類
[Custom("這是一個業務邏輯類", Author = "John Doe", Priority = 1)]
[Serializable]
public class Product
{
    [Validation(Required = true, MinLength = 3, MaxLength = 50)]
    public string Name { get; set; }
    
    [Validation(Required = true)]
    [Obsolete("請使用 DecimalPrice 屬性")]
    public double Price { get; set; }
    
    public decimal DecimalPrice { get; set; }
    
    [Custom("這是庫存屬性")]
    public int Stock { get; set; }
    
    [Custom("計算折扣價格的方法", Priority = 2)]
    public decimal CalculateDiscount(decimal discountRate)
    {
        return DecimalPrice * (1 - discountRate);
    }
}

// 反射演示
class ReflectionDemo
{
    public static void Demo()
    {
        Console.WriteLine("=== 反射基礎 ===\n");
        
        Type productType = typeof(Product);
        
        // 獲取類型信息
        Console.WriteLine($"類型名稱: {productType.Name}");
        Console.WriteLine($"全名: {productType.FullName}");
        Console.WriteLine($"命名空間: {productType.Namespace}");
        Console.WriteLine($"是否是類: {productType.IsClass}");
        Console.WriteLine($"是否是值類型: {productType.IsValueType}");
        Console.WriteLine($"基類型: {productType.BaseType?.Name}");
        
        // 獲取屬性
        Console.WriteLine("\n=== 屬性信息 ===");
        var properties = productType.GetProperties(
            BindingFlags.Public | BindingFlags.Instance);
        
        foreach (var prop in properties)
        {
            Console.WriteLine($"屬性: {prop.Name}");
            Console.WriteLine($"  類型: {prop.PropertyType.Name}");
            Console.WriteLine($"  可讀: {prop.CanRead}");
            Console.WriteLine($"  可寫: {prop.CanWrite}");
            
            // 獲取屬性上的特性
            var attributes = prop.GetCustomAttributes();
            foreach (var attr in attributes)
            {
                Console.WriteLine($"  特性: {attr.GetType().Name}");
                
                if (attr is ValidationAttribute validationAttr)
                {
                    Console.WriteLine($"    Required: {validationAttr.Required}");
                    Console.WriteLine($"    MinLength: {validationAttr.MinLength}");
                    Console.WriteLine($"    MaxLength: {validationAttr.MaxLength}");
                }
            }
        }
        
        // 獲取方法
        Console.WriteLine("\n=== 方法信息 ===");
        var methods = productType.GetMethods(
            BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        
        foreach (var method in methods)
        {
            Console.WriteLine($"方法: {method.Name}");
            Console.WriteLine($"  返回類型: {method.ReturnType.Name}");
            
            var parameters = method.GetParameters();
            if (parameters.Length > 0)
            {
                Console.WriteLine($"  參數:");
                foreach (var param in parameters)
                {
                    Console.WriteLine($"    {param.ParameterType.Name} {param.Name}");
                }
            }
        }
        
        // 獲取特性
        Console.WriteLine("\n=== 類型特性 ===");
        var typeAttributes = productType.GetCustomAttributes();
        foreach (var attr in typeAttributes)
        {
            Console.WriteLine($"特性: {attr.GetType().Name}");
            
            if (attr is CustomAttribute customAttr)
            {
                Console.WriteLine($"  描述: {customAttr.Description}");
                Console.WriteLine($"  作者: {customAttr.Author}");
                Console.WriteLine($"  優先級: {customAttr.Priority}");
                Console.WriteLine($"  日期: {customAttr.Date}");
            }
        }
        
        // 動態創建實例
        Console.WriteLine("\n=== 動態創建實例 ===");
        object productInstance = Activator.CreateInstance(productType);
        
        // 動態設置屬性
        PropertyInfo nameProperty = productType.GetProperty("Name");
        nameProperty.SetValue(productInstance, "筆記本電腦");
        
        PropertyInfo priceProperty = productType.GetProperty("DecimalPrice");
        priceProperty.SetValue(productInstance, 2999.99m);
        
        // 動態讀取屬性
        string name = (string)nameProperty.GetValue(productInstance);
        decimal price = (decimal)priceProperty.GetValue(productInstance);
        Console.WriteLine($"產品: {name}, 價格: {price:C}");
        
        // 動態調用方法
        Console.WriteLine("\n=== 動態調用方法 ===");
        MethodInfo discountMethod = productType.GetMethod("CalculateDiscount");
        object discountResult = discountMethod.Invoke(productInstance, new object[] { 0.1m });
        Console.WriteLine($"折扣後價格: {discountResult:C}");
        
        // 使用 dynamic 關鍵字
        Console.WriteLine("\n=== 使用 dynamic ===");
        dynamic dynamicProduct = Activator.CreateInstance(productType);
        dynamicProduct.Name = "智能手機";
        dynamicProduct.DecimalPrice = 1999.99m;
        
        decimal dynamicDiscount = dynamicProduct.CalculateDiscount(0.15m);
        Console.WriteLine($"動態產品折扣: {dynamicDiscount:C}");
        
        // 程序集操作
        Console.WriteLine("\n=== 程序集信息 ===");
        Assembly currentAssembly = Assembly.GetExecutingAssembly();
        Console.WriteLine($"程序集名稱: {currentAssembly.GetName().Name}");
        Console.WriteLine($"版本: {currentAssembly.GetName().Version}");
        
        // 獲取程序集中的所有類型
        var allTypes = currentAssembly.GetTypes();
        Console.WriteLine($"程序集中類型數量: {allTypes.Length}");
        
        // 查找實現特定接口的類型
        var serializableTypes = allTypes.Where(t => 
            t.GetCustomAttribute<SerializableAttribute>() != null);
        
        Console.WriteLine($"可序列化類型: {serializableTypes.Count()}");
        
        // 特性驗證示例
        Console.WriteLine("\n=== 特性驗證 ===");
        Product testProduct = new Product();
        ValidateProduct(testProduct);
        
        testProduct.Name = "AB"; // 太短
        ValidateProduct(testProduct);
        
        testProduct.Name = "有效的產品名稱";
        ValidateProduct(testProduct);
    }
    
    static void ValidateProduct(Product product)
    {
        var properties = typeof(Product).GetProperties();
        
        foreach (var property in properties)
        {
            var validationAttr = property.GetCustomAttribute<ValidationAttribute>();
            if (validationAttr != null)
            {
                object value = property.GetValue(product);
                
                if (validationAttr.Required && value == null)
                {
                    Console.WriteLine($"{property.Name}: 必須提供值");
                }
                
                if (value is string stringValue)
                {
                    if (stringValue.Length < validationAttr.MinLength)
                    {
                        Console.WriteLine($"{property.Name}: 長度不能少於 {validationAttr.MinLength}");
                    }
                    
                    if (stringValue.Length > validationAttr.MaxLength && validationAttr.MaxLength > 0)
                    {
                        Console.WriteLine($"{property.Name}: 長度不能超過 {validationAttr.MaxLength}");
                    }
                }
            }
        }
    }
}

// 表達式樹
class ExpressionTreeDemo
{
    public static void Demo()
    {
        Console.WriteLine("=== 表達式樹 ===\n");
        
        // 創建表達式: x => x * 2
        ParameterExpression parameter = Expression.Parameter(typeof(int), "x");
        ConstantExpression constant = Expression.Constant(2, typeof(int));
        BinaryExpression multiply = Expression.Multiply(parameter, constant);
        
        LambdaExpression lambda = Expression.Lambda<Func<int, int>>(multiply, parameter);
        
        // 編譯表達式
        Func<int, int> func = (Func<int, int>)lambda.Compile();
        
        // 執行
        int result = func(5);
        Console.WriteLine($"5 * 2 = {result}");
        
        // 動態構建複雜表達式
        Console.WriteLine("\n=== 動態構建查詢表達式 ===");
        
        // 構建: x => x > 5 && x < 10
        ParameterExpression param = Expression.Parameter(typeof(int), "x");
        ConstantExpression five = Expression.Constant(5, typeof(int));
        ConstantExpression ten = Expression.Constant(10, typeof(int));
        
        BinaryExpression greaterThan = Expression.GreaterThan(param, five);
        BinaryExpression lessThan = Expression.LessThan(param, ten);
        BinaryExpression and = Expression.AndAlso(greaterThan, lessThan);
        
        LambdaExpression lambda2 = Expression.Lambda<Func<int, bool>>(and, param);
        Func<int, bool> filter = (Func<int, bool>)lambda2.Compile();
        
        // 測試
        int[] numbers = { 1, 3, 5, 7, 9, 11 };
        var filtered = numbers.Where(filter);
        Console.WriteLine($"過濾結果: {string.Join(", ", filtered)}");
        
        // 屬性訪問表達式
        Console.WriteLine("\n=== 屬性訪問表達式 ===");
        
        ParameterExpression productParam = Expression.Parameter(typeof(Product), "p");
        MemberExpression nameProperty = Expression.Property(productParam, "Name");
        ConstantExpression searchValue = Expression.Constant("筆記本", typeof(string));
        
        MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
        MethodCallExpression containsCall = Expression.Call(nameProperty, containsMethod, searchValue);
        
        LambdaExpression searchLambda = Expression.Lambda<Func<Product, bool>>(containsCall, productParam);
        Func<Product, bool> searchFunc = (Func<Product, bool>)searchLambda.Compile();
        
        // 這只是演示,實際使用時會配合數據源
    }
}

C# 新特性

C# 8.0-12.0 新特性

csharp

class CSharpNewFeatures
{
    public static void Demo()
    {
        Console.WriteLine("=== C# 8.0-12.0 新特性演示 ===\n");
        
        // 1. 可空引用類型 (C# 8.0)
        NullableReferenceTypes();
        
        // 2. 模式匹配增強 (C# 8.0, 9.0, 11.0)
        PatternMatching();
        
        // 3. 索引和範圍 (C# 8.0)
        IndicesAndRanges();
        
        // 4. 默認接口方法 (C# 8.0)
        DefaultInterfaceMethods();
        
        // 5. 記錄類型 (C# 9.0)
        RecordTypes();
        
        // 6. 僅初始化屬性 (C# 9.0)
        InitOnlyProperties();
        
        // 7. 頂層語句 (C# 9.0)
        // 注意:這主要在 Program.cs 中使用
        
        // 8. 模式匹配增強 (C# 9.0)
        EnhancedPatternMatching();
        
        // 9. 目標類型 new 表達式 (C# 9.0)
        TargetTypedNew();
        
        // 10. 全局 using 語句 (C# 10.0)
        // 在文件頂部使用:global using System;
        
        // 11. 文件範圍的命名空間 (C# 10.0)
        // namespace MyNamespace; // 不需要大括號
        
        // 12. 原始字符串字面量 (C# 11.0)
        RawStringLiterals();
        
        // 13. 泛型屬性 (C# 11.0)
        GenericAttributes();
        
        // 14. 必需的成員 (C# 11.0)
        RequiredMembers();
        
        // 15. 列表模式 (C# 11.0)
        ListPatterns();
        
        // 16. 主構造函數 (C# 12.0)
        PrimaryConstructors();
        
        // 17. 集合表達式 (C# 12.0)
        CollectionExpressions();
        
        // 18. 默認 Lambda 參數 (C# 12.0)
        DefaultLambdaParameters();
    }
    
    static void NullableReferenceTypes()
    {
        Console.WriteLine("1. 可空引用類型 (C# 8.0):");
        
        // 啟用可空引用類型後,引用類型默認不可為空
        string nonNullable = "Hello"; // 正常
        // string nullString = null; // 警告
        
        // 明確聲明可空
        string? nullableString = null; // 正常
        
        // 空容許上下文
#nullable disable
        string disabledNullable = null; // 沒有警告
#nullable restore
        
        Console.WriteLine("  可空引用類型已啟用\n");
    }
    
    static void PatternMatching()
    {
        Console.WriteLine("2. 模式匹配增強:");
        
        object obj = "Hello";
        
        // 屬性模式 (C# 8.0)
        if (obj is string { Length: > 3 } s)
        {
            Console.WriteLine($"  長字符串: {s}");
        }
        
        // 元組模式 (C# 8.0)
        var point = (5, 10);
        var result = point switch
        {
            (0, 0) => "原點",
            (var x, var y) when x == y => "對角線",
            (_, _) => "其他點"
        };
        Console.WriteLine($"  元組模式: {result}");
        
        // 位置模式 (C# 8.0)
        var shape = new Rectangle(10, 20);
        if (shape is (10, 20))
        {
            Console.WriteLine($"  匹配的矩形: 10x20");
        }
        
        Console.WriteLine();
    }
    
    static void IndicesAndRanges()
    {
        Console.WriteLine("3. 索引和範圍 (C# 8.0):");
        
        int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        
        // ^ 運算符表示從末尾開始
        int last = numbers[^1]; // 9
        int secondLast = numbers[^2]; // 8
        
        // .. 運算符表示範圍
        var slice1 = numbers[1..4]; // [1, 2, 3]
        var slice2 = numbers[..3]; // [0, 1, 2]
        var slice3 = numbers[6..]; // [6, 7, 8, 9]
        var slice4 = numbers[..]; // 全部
        var slice5 = numbers[^3..]; // [7, 8, 9]
        
        Console.WriteLine($"  最後一個: {last}");
        Console.WriteLine($"  倒數第二個: {secondLast}");
        Console.WriteLine($"  範圍 1..4: {string.Join(", ", slice1)}");
        
        Console.WriteLine();
    }
    
    static void DefaultInterfaceMethods()
    {
        Console.WriteLine("4. 默認接口方法 (C# 8.0):");
        
        ILogger logger = new ConsoleLogger();
        logger.Log("信息"); // 調用默認實現
        logger.LogError("錯誤"); // 調用重寫實現
        
        Console.WriteLine();
    }
    
    static void RecordTypes()
    {
        Console.WriteLine("5. 記錄類型 (C# 9.0):");
        
        // 記錄類型 - 不可變數據類型
        var person1 = new PersonRecord("Alice", 25);
        var person2 = new PersonRecord("Alice", 25);
        
        // 值相等性
        Console.WriteLine($"  person1 == person2: {person1 == person2}");
        
        // with 表達式創建修改的副本
        var person3 = person1 with { Age = 26 };
        Console.WriteLine($"  修改後的副本: {person3}");
        
        // 解構
        var (name, age) = person1;
        Console.WriteLine($"  解構: {name}, {age}");
        
        // 位置記錄
        var point = new PointRecord(10, 20);
        Console.WriteLine($"  位置記錄: {point}");
        
        Console.WriteLine();
    }
    
    static void InitOnlyProperties()
    {
        Console.WriteLine("6. 僅初始化屬性 (C# 9.0):");
        
        var config = new AppConfig
        {
            Name = "MyApp",
            Version = "1.0.0"
            // 初始化後不能再修改
        };
        
        // config.Name = "NewName"; // 編譯錯誤
        
        Console.WriteLine($"  配置: {config.Name} v{config.Version}\n");
    }
    
    static void EnhancedPatternMatching()
    {
        Console.WriteLine("8. 增強的模式匹配 (C# 9.0):");
        
        // 關係模式
        int score = 85;
        var grade = score switch
        {
            >= 90 => "A",
            >= 80 => "B",
            >= 70 => "C",
            >= 60 => "D",
            _ => "F"
        };
        Console.WriteLine($"  分數 {score} => 等級 {grade}");
        
        // 邏輯模式
        object value = 42;
        if (value is not null and int n)
        {
            Console.WriteLine($"  不是 null 且是整數: {n}");
        }
        
        Console.WriteLine();
    }
    
    static void TargetTypedNew()
    {
        Console.WriteLine("9. 目標類型 new 表達式 (C# 9.0):");
        
        // 不需要重複類型
        Person person = new("Bob", 30);
        List<string> names = new() { "Alice", "Bob", "Charlie" };
        
        Console.WriteLine($"  創建對象: {person.Name}\n");
    }
    
    static void RawStringLiterals()
    {
        Console.WriteLine("12. 原始字符串字面量 (C# 11.0):");
        
        string json = """
            {
                "name": "Alice",
                "age": 30,
                "address": "123 Main St"
            }
            """;
        
        Console.WriteLine($"  JSON 字符串:\n{json}\n");
        
        // 帶插值的原始字符串
        string name = "Alice";
        string interpolated = $"""
            你好 {name}!
            這是一個多行
            原始字符串。
            """;
        Console.WriteLine(interpolated + "\n");
    }
    
    static void GenericAttributes()
    {
        Console.WriteLine("13. 泛型屬性 (C# 11.0):");
        
        // 之前: [Custom(typeof(MyClass))]
        // 現在: [Custom<MyClass>]
        
        Console.WriteLine("  泛型屬性現在可以直接使用\n");
    }
    
    static void RequiredMembers()
    {
        Console.WriteLine("14. 必需的成員 (C# 11.0):");
        
        // 使用 required 關鍵字
        var user = new User 
        { 
            Username = "alice", // 必須初始化
            Email = "alice@example.com" // 必須初始化
        };
        
        Console.WriteLine($"  用戶: {user.Username}\n");
    }
    
    static void ListPatterns()
    {
        Console.WriteLine("15. 列表模式 (C# 11.0):");
        
        int[] numbers = { 1, 2, 3, 4, 5 };
        
        if (numbers is [1, 2, .., 5])
        {
            Console.WriteLine("  匹配列表模式 [1, 2, .., 5]");
        }
        
        // 切片模式
        var result = numbers switch
        {
            [] => "空數組",
            [1] => "只有 1",
            [1, 2] => "1, 2",
            [1, .. var middle, 5] => $"以 1 開始,5 結束,中間有 {middle.Length} 個元素",
            _ => "其他"
        };
        
        Console.WriteLine($"  結果: {result}\n");
    }
    
    static void PrimaryConstructors()
    {
        Console.WriteLine("16. 主構造函數 (C# 12.0):");
        
        var student = new Student("Alice", 20);
        Console.WriteLine($"  學生: {student.Name}, {student.Age}歲\n");
    }
    
    static void CollectionExpressions()
    {
        Console.WriteLine("17. 集合表達式 (C# 12.0):");
        
        // 統一語法
        int[] array1 = [1, 2, 3, 4, 5];
        List<int> list1 = [1, 2, 3, 4, 5];
        Span<int> span1 = [1, 2, 3, 4, 5];
        
        // 展開運算符
        int[] part1 = [1, 2, 3];
        int[] part2 = [4, 5, 6];
        int[] combined = [.. part1, .. part2];
        
        Console.WriteLine($"  合併數組: {string.Join(", ", combined)}\n");
    }
    
    static void DefaultLambdaParameters()
    {
        Console.WriteLine("18. 默認 Lambda 參數 (C# 12.0):");
        
        var addWithDefault = (int x, int y = 1) => x + y;
        Console.WriteLine($"  默認參數 Lambda: addWithDefault(5) = {addWithDefault(5)}");
        Console.WriteLine($"  addWithDefault(5, 3) = {addWithDefault(5, 3)}\n");
    }
}

// 記錄類型定義
public record PersonRecord(string Name, int Age);

public record PointRecord(int X, int Y)
{
    public double Distance => Math.Sqrt(X * X + Y * Y);
}

// 僅初始化屬性
public class AppConfig
{
    public string Name { get; init; }
    public string Version { get; init; }
}

// 默認接口方法
public interface ILogger
{
    void Log(string message)
    {
        Console.WriteLine($"  日誌: {message}");
    }
    
    void LogError(string error);
}

public class ConsoleLogger : ILogger
{
    public void LogError(string error)
    {
        Console.WriteLine($"  錯誤: {error}");
    }
}

// 必需的成員
public class User
{
    public required string Username { get; init; }
    public required string Email { get; init; }
    public string? Phone { get; init; }
}

// 主構造函數 (C# 12.0)
public class Student(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;
    
    // 可以在類體中使用主構造函數參數
    public string Info => $"{Name} ({Age})";
}

總結

C# 是一門功能豐富、不斷發展的現代編程語言。從基礎的語法和數據類型,到面向對象編程、泛型、LINQ、異步編程,再到最新的語言特性,C# 提供了強大的工具來構建各種類型的應用程序。

C# 的主要優勢:

  1. 類型安全:強類型系統幫助在編譯時捕獲錯誤

  2. 面向對象:完整的 OOP 支持

  3. 現代語法:不斷引入新特性保持語言的現代性

  4. 強大的框架:.NET 框架提供了豐富的庫

  5. 跨平台:.NET Core/.NET 5+ 支持跨平台開發

  6. 性能優秀:編譯為本地代碼,性能接近 C++

學習建議:

  1. 掌握基礎:深入理解類型系統、OOP 概念

  2. 熟悉框架:學習 .NET 標準庫和常用框架

  3. 實踐項目:通過實際項目應用所學知識

  4. 關注發展:關注 C# 和 .NET 的新特性

  5. 閱讀源碼:閱讀優秀開源項目的源代碼

C# 的學習曲線相對平緩,但深度很大。隨著經驗的積累,你會發現這門語言能夠優雅地解決複雜的問題,是企業級應用開發的優秀選擇。


版權聲明:本文檔僅供學習參考,代碼示例可以自由使用和修改。部分高級特性可能需要特定版本的 .NET SDK 支持。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐