ภาพรวม
ใน C# สามารถใช้ switch ซ้อนกันได้ (Nested Switch) โดยวาง switch ภายใน case ของ switch อื่น แม้ค่า Case ของ Inner และ Outer จะซ้ำกัน ก็ไม่เกิด Conflict เพราะ Scope แยกกัน
ไวยากรณ์
switch (outerVar)
{
case 'A':
Console.WriteLine("Outer A");
switch (innerVar)
{
case 'A':
Console.WriteLine("Inner A");
break;
case 'B':
// Inner B
break;
}
break; // สำคัญ: Break ของ Outer Case
case 'B':
// Outer B
break;
}ตัวอย่างโปรแกรม
using System;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
int a = 100;
int b = 200;
switch (a)
{
case 100:
Console.WriteLine("นี่เป็นส่วนของ Outer Switch");
switch (b)
{
case 200:
Console.WriteLine("นี่เป็นส่วนของ Inner Switch");
break;
}
break; // จบ Outer Case 100
}
Console.WriteLine("ค่าที่แท้จริงของ a: {0}", a);
Console.WriteLine("ค่าที่แท้จริงของ b: {0}", b);
Console.ReadLine();
}
}
}ผลลัพธ์
นี่เป็นส่วนของ Outer Switch นี่เป็นส่วนของ Inner Switch ค่าที่แท้จริงของ a: 100 ค่าที่แท้จริงของ b: 200
Switch Expression (C# 8.0+) - ทางเลือกที่ทันสมัยกว่า
แทน Nested Switch ให้ใช้ Switch Expression ที่กระชับและเป็น Functional Style:
// Nested Switch แบบเก่า
string result = "";
switch (a)
{
case 100:
switch (b)
{
case 200: result = "A=100, B=200"; break;
case 300: result = "A=100, B=300"; break;
}
break;
}
// Switch Expression (C# 8+)
string result = (a, b) switch
{
(100, 200) => "A=100, B=200",
(100, 300) => "A=100, B=300",
(200, _) => "A=200",
_ => "Other"
};Pattern Matching Switch (C# 7.0+)
switch (obj)
{
case int i when i > 0:
Console.WriteLine("Positive int: " + i);
break;
case string s when s.Length > 5:
Console.WriteLine("Long string: " + s);
break;
case null:
Console.WriteLine("Null");
break;
default:
Console.WriteLine("Other");
break;
}ข้อสังเกตสำคัญ
- Nested Switch ทำงานได้ แต่มักทำให้โค้ดซับซ้อน (Spaghetti Code)
- แต่ละ
caseต้องมีbreak(หรือreturn/throw/goto) มิฉะนั้นจะ Fall-through (Compile Error ใน C# ยกเว้น Case ว่าง) - Case Label ซ้อนกันได้ เพราะ Scope แยกกัน
- แนะนำให้ Refactor เป็น:
- Switch Expression (Tuple Pattern)
- Dictionary Lookup
- Polymorphism / Strategy Pattern
- Guard Clauses + Early Return
Best Practice: หลีกเลี่ยง Nested Switch
// แทน Nested Switch
public string GetMessage(int a, int b)
{
return (a, b) switch
{
(100, 200) => "Outer 100, Inner 200",
(100, 300) => "Outer 100, Inner 300",
(200, _) => "Outer 200",
_ => "Unknown"
};
}