Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Pattern Matching ใน C# 7.0 คืออะไร

C# 7.0 Introduce Pattern Matching ใน 2 กรณี: is Expression และ switch Statement

Patterns ทดสอบว่า Value มี Shape เฉพาะหรือไม่ และสามารถ Extract Information จาก Value เมื่อ Match ได้

Pattern Matching ให้ Syntax ที่ Concise มากกว่าสำหรับ Algorithms

สามารถ Pattern Match บน Data Type ใดๆ ได้ แม้ Custom Types (If/Else ต้องใช้ Primitives)

Pattern Matching สามารถ Extract Values จาก Expression ได้

ก่อน Pattern Matching (If/Else + Cast)


public class PI {
    public const float Pi = 3.142f;
}

public class Rectangle : PI {
    public double Width { get; set; }
    public double Height { get; set; }
}

public class Circle : PI {
    public double Radius { get; set; }
}

class Program {
    public static void PrintArea(PI pi) {
        if (pi is Rectangle) {
            Rectangle rectangle = pi as Rectangle;  // Cast อีกครั้ง
            Console.WriteLine($"Area of Rect: {rectangle.Width * rectangle.Height}");
        }
        else if (pi is Circle) {
            Circle c = pi as Circle;  // Cast อีกครั้ง
            Console.WriteLine($"Area of Circle: {Circle.Pi * c.Radius * c.Radius}");
        }
    }
    
    public static void Main() {
        Rectangle r1 = new Rectangle { Width = 12.2, Height = 33 };
        Rectangle r2 = new Rectangle { Width = 12.2, Height = 44 };
        Circle c1 = new Circle { Radius = 12 };
        
        PrintArea(r1);
        PrintArea(r2);
        PrintArea(c1);
        Console.ReadLine();
    }
}

หลัง Pattern Matching (Type Pattern + Variable Declaration)


class Program {
    public static void PrintArea(PI pi) {
        // Type Pattern: ตรวจสอบ Type และ Declare Variable พร้อมกัน
        if (pi is Rectangle rectangle) {
            Console.WriteLine($"Area of Rect: {rectangle.Width * rectangle.Height}");
        }
        else if (pi is Circle c) {
            Console.WriteLine($"Area of Circle: {Circle.Pi * c.Radius * c.Radius}");
        }
    }
    
    public static void Main() {
        Rectangle r1 = new Rectangle { Width = 12.2, Height = 33 };
        Rectangle r2 = new Rectangle { Width = 12.2, Height = 44 };
        Circle c1 = new Circle { Radius = 12 };
        
        PrintArea(r1);
        PrintArea(r2);
        PrintArea(c1);
        Console.ReadLine();
    }
}

Output


Area of Rect: 402.6
Area of Rect: 536.8
Area of Circle: 452.448

Pattern Matching ใน Switch Statement (C# 7.0)


public static string Describe(object obj) {
    switch (obj) {
        case null:
            return "Null";
        
        case int i when i > 0:      // Type Pattern + When Clause
            return $"Positive Integer: {i}";
        
        case int i:
            return $"Integer: {i}";
        
        case string s when s.Length > 10:
            return $"Long String: {s}";
        
        case string s:
            return $"String: {s}";
        
        case double d:
            return $"Double: {d:F2}";
        
        case Rectangle r when r.Width > r.Height:
            return $"Wide Rectangle: {r.Width}x{r.Height}";
        
        case Rectangle r:
            return $"Rectangle: {r.Width}x{r.Height}";
        
        case Circle c:
            return $"Circle: Radius={c.Radius}";
        
        default:
            return "Unknown";
    }
}

Pattern Types ใน C# 7.0

PatternSyntaxExample
Constant Patterncase constant:case 0:, case "test":
Type Patterncase Type varName:case int i:, case string s:
Var Patterncase var x:Match ทุกอย่าง (เหมือน default แต่ Capture Value)
When Clausecase Type v when condition:case int i when i > 0:

Pattern Matching Evolution (C# 7.0 → 9.0+)


// C# 7.0: Type Pattern, Const Pattern, When Clause
obj switch {
    int i => i.ToString(),
    string s => s,
    _ => "Unknown"
}

// C# 8.0: Switch Expressions, Property Patterns
obj switch {
    { Length: > 10 } => "Long",
    { Length: 0 } => "Empty",
    _ => "Normal"
}

// C# 9.0: Relational Patterns, Logical Patterns
score switch {
    >= 90 => "A",
    >= 80 => "B",
    _ => "F"
}

input switch {
    > 0 and < 100 => "Valid",
    < 0 or > 100 => "Invalid",
    0 => "Zero"
}

// C# 10.0: Extended Property Patterns
person switch {
    { Address: { City: "Bangkok" } } => "Local",
    { Address: { Country: "Thailand" } } => "Domestic",
    _ => "International"
}

ข้อดีของ Pattern Matching

  • Concise: ลด Boilerplate Code (is + cast → pattern)
  • Readable: Logic ชัดเจน Declarative Style
  • Type Safe: Compiler ช่วย Check Exhaustiveness
  • Extensible: เพิ่ม Patterns ใหม่ได้ง่าย
  • Performance: Compiler Optimize ได้ดีกว่า If/Else Chain