Menu
flag Ar iconالعربيةdown icon

تعبير switch في C#: الصياغة والأنماط والمُهمَل _ وwhen

يحوّل تعبير switch في C# 8 قيمة إلى نتيجة بأذرع نمطية بدل case وbreak. الصياغة، والمُهمَل _، وأنماط الخصائص والصفوف والعلائقية، وand/or/not، وحراسات when، وتحذيرات الشمول وSwitchExpressionException، مع مكافئات C# 7 قابلة للتشغيل.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

يربط تعبير switch قيمة مدخلة بنتيجة. أُضيف في C# 8 ويحلّ محل النمط الشائع لجملة switch لا تفعل كل حالة فيها سوى إعادة شيء أو إسناده:

// C# 8 and later
string StatusText(int code) => code switch
{
    200 => "OK",
    301 or 302 => "Redirect",   // 'or' needs C# 9
    404 => "Not Found",
    >= 500 => "Server Error",   // relational patterns need C# 9
    _ => "Unknown"
};

اقرأه من الأعلى إلى الأسفل: تُختبر القيمة التي قبل switch مقابل كل ذراع بالترتيب، وأول ذراع يطابق نمطها تقدّم النتيجة. لا توجد case ولا break ولا الكلمة default؛ ونمط المُهمَل _ يطابق أي شيء ويعمل كبديل أخير.

في C# 7 يكون الربط نفسه جملة switch في دالة صغيرة، مع return في كل حالة:

المخرجات:

200 OK
302 Redirect
404 Not Found
503 Server Error
418 Unknown

الشكل التعبيري أقصر أساسًا لأن كل ذراع سطر واحد واختفى جسم الدالة. وهو أيضًا تعبير، فيمكن أن يوضع في أي مكان تُوضع فيه قيمة: وسيط، أو فتحة استيفاء، أو return، أو مهيّئ حقل.

قواعد الصياغة

var result = input switch
{
    pattern1 => value1,
    pattern2 when condition => value2,
    _ => fallback
};
  • تأتي المدخلات أولًا، ثم switch. وهذا عكس شكل الجملة.
  • كل ذراع بالشكل pattern => expression. ويجب أن يكون ما بعد السهم تعبيرًا واحدًا؛ ولمنطق أكثر استدعِ دالة.
  • تُفصل الأذرع بفواصل. ويُسمح بفاصلة زائدة بعد الذراع الأخيرة.
  • الكل تعبير، فتنتهي العبارة التي تستخدمه بـ ; بعد القوس الختامي.
  • يجب أن تنتج كل الأذرع قيمًا من نوع مشترك. لا تُترجم var x = n switch { 0 => "zero", _ => 0 }; (CS8506، لا يوجد نوع أفضل). ومنذ C# 9 يحسم نوع الهدف المصرّح به المسألة: object x = n switch { 0 => "zero", _ => 0 }; تُترجم.
  • يجب أن تنتج كل ذراع قيمة، فلا يمكن للذراع استدعاء دالة void مثل Console.WriteLine، ولا يمكن لتعبير switch أن يقف وحده كعبارة (CS0201). للأفعال استخدم جملة switch.
  • يمكن للذراع أن ترمي استثناءً بدل إنتاج قيمة: _ => throw new ArgumentOutOfRangeException(nameof(input)).
  • يرفض المترجم الذراع التي لا يمكن الوصول إليها أبدًا لأن ذراعًا سابقة تغطيها أصلًا، بالخطأ CS8510، The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match. ضع الأذرع المحددة قبل العامة.

الأنماط العلائقية والمنطقية (C# 9)

أضافت C# 9 المعاملات < و<= و> و>= كأنماط، والروابط and وor وnot. وهي تجعل جداول النطاقات تُقرأ كمواصفات:

// C# 9 and later
string Grade(int score) => score switch
{
    < 0 or > 100 => throw new ArgumentOutOfRangeException(nameof(score)),
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    >= 60 => "D",
    _ => "F"
};

string AgeGroup(int age) => age switch
{
    < 13 => "child",
    >= 13 and <= 19 => "teen",
    _ => "adult"
};

bool IsLetter(char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';

ولأن الأذرع تُجرَّب بالترتيب، لا ترى >= 80 إلا الدرجات الأقل من 90. لا تأخذ الأنماط العلائقية إلا ثوابت بعد المعامل؛ وللمقارنة بمتغيّر استخدم حراسة when. مكافئ جدول النطاقات في C# 7 سلسلة if:

المخرجات:

95 -> A
83 -> B
71 -> C
64 -> D
12 -> F

تُستخدم not غالبًا بالشكل not null: x is not null، أو ذراع not null => x.Name.

أنماط الخصائص

يطابق نمط الخاصية أعضاء كائن: { Property: pattern, ... }. ومع تعبير switch يعبّر عن قواعد العمل دون سلسلة شروط &&:

// C# 8 and later
decimal ShippingCost(Order order) => order switch
{
    { Total: >= 100m } => 0m,                       // relational inside: C# 9
    { Country: "US", Express: true } => 15m,
    { Country: "US" } => 5m,
    { Express: true } => 30m,
    null => throw new ArgumentNullException(nameof(order)),
    _ => 12m
};

يجب أن تطابق كل خاصية مذكورة كي تطابق الذراع. ونمط الخاصية الفارغ { } يطابق أي قيمة غير null. أضافت C# 10 أنماط الخصائص الموسّعة للأعضاء المتداخلة: { Customer.Address.Country: "US" } بدل { Customer: { Address: { Country: "US" } } }.

أنماط الصفوف

التفرّع على صف يطابق عدة قيم دفعة واحدة، وهي الطريقة النظيفة للتعبير عن جدول قرارات:

// C# 9 and later (the 'or' pattern)
string Winner(string a, string b) => (a, b) switch
{
    ("rock", "scissors") or ("scissors", "paper") or ("paper", "rock") => "player 1",
    var (x, y) when x == y => "draw",
    _ => "player 2"
};

تفكّك var (x, y) الصف إلى متغيّرين يمكن لحراسة when مقارنتهما. في C# 7 البديل المعتاد دمج القيم في مفتاح واحد، أو استخدام قاموس للنتائج:

المخرجات:

player 1
player 2
draw

أنماط الأنواع وwhen

يمكن للذراع اختبار النوع وقت التشغيل وربط متغيّر، ويضيف بند when أي شرط لا تستطيع صياغة الأنماط التعبير عنه:

// C# 8 and later
double Area(Shape shape) => shape switch
{
    Circle c => Math.PI * c.Radius * c.Radius,
    Rectangle r when r.Width == r.Height => r.Width * r.Width,
    Rectangle r => r.Width * r.Height,
    null => throw new ArgumentNullException(nameof(shape)),
    _ => throw new NotSupportedException(shape.GetType().Name)
};

تستخدم نسخة C# 7 نمط النوع is في سلسلة if، الذي يربط المتغيّر بالطريقة نفسها:

المخرجات:

Circle: 12.57
Rectangle: 13.50

الشمول وSwitchExpressionException

يجب أن ينتج تعبير switch قيمة لكل مدخل. حين يرى المترجم مدخلات لا تطابقها أي ذراع يحذّر:

warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '0' is not covered.

هو تحذير لا خطأ، فتُبنى الشيفرة. وإن وصلت قيمة غير مطابقة وقت التشغيل يرمي التعبير System.Runtime.CompilerServices.SwitchExpressionException، التي تنتهي رسالتها بالقيمة غير المطابقة (Unmatched value was 3.).

للتعدادات حالة خاصة. حتى حين يكون لكل عضو مسمّى ذراع، يمكن لمتغيّر التعداد أن يحمل أي عدد صحيح ((Size)3)، فيبلّغ المترجم بـ CS8524 عن "قيمة تعداد غير مسمّاة":

// C# 8 and later
enum Size { Small, Medium, Large }

string Code(Size s) => s switch
{
    Size.Small => "S",
    Size.Medium => "M",
    Size.Large => "L",
    // warning CS8524 without the next arm
    _ => throw new ArgumentOutOfRangeException(nameof(s))
};

أضف ذراع _ صريحة ترمي استثناءً مفيدًا. هذا يوثّق الافتراض، ويسكت التحذير، ويعطي خطأ أوضح من SwitchExpressionException إن ظهرت قيمة سيئة يومًا.

القاموس كبديل

حين تكون الأذرع أزواج ثابت إلى قيمة خالصة وقد يكبر الجدول أو يأتي من الإعدادات، يؤدي Dictionary المهمة نفسها في أي إصدار من C# ويمكن بناؤه وقت التشغيل:

المخرجات:

19.00
11.50
0

يحصل البلد غير المعروف على نسبة 0m. لحاصل ضرب decimal عدد منازل عشرية يساوي مجموع منازل معامليه، ولهذا تُطبع 100m * 0.19m كـ 19.00 وتُطبع النسبة الصفرية 0.

تعبير switch مقابل جملة switch

جملة switchتعبير switch
متاح منذC# 1C# 8
ينتج قيمةلانعم
الصياغة لكل فرعcase X: ... break;X => value,
البديل الأخيرdefault:_ =>
عدة عبارات لكل فرعنعملا، استدعِ دالة
تحذير الشموللانعم (CS8509)
لا تطابق وقت التشغيللا يُنفَّذ شيءSwitchExpressionException

يأخذ الشكلان الأنماط نفسها (الأنواع والثوابت والخصائص والصفوف والعلائقية)، فتعلّم أحدهما يعلّمك الآخر. الاختيار مسألة شكل: القيمة تمر عبر التعبير، وتسلسل الأفعال يمر عبر الجملة.

الأسئلة الشائعة

ما هو تعبير switch في C#؟

تعبير switch، المضاف في C# 8، يُقيَّم إلى قيمة: string text = code switch { 200 => "OK", 404 => "Not Found", _ => "Unknown" };. تأتي المدخلات قبل الكلمة switch، وكل ذراع بالشكل pattern => result، وتُفصل الأذرع بفواصل، ولا توجد الكلمات case ولا break ولا default.

ما هي الحالة الافتراضية في تعبير switch في C#؟

نمط المُهمَل _ يطابق أي شيء، فتؤدي _ => "Unknown" كذراع أخيرة دور default. دون ذراع تلتقط كل شيء يحذّر المترجم (CS8509) حين لا تُغطّى بعض المدخلات، وترمي القيمة غير المطابقة وقت التشغيل SwitchExpressionException.

كيف أطابق عدة قيم في ذراع واحدة من تعبير switch؟

استخدم النمط or من C# 9: "sat" or "sun" => "weekend". وللنطاقات اجمع الأنماط العلائقية بـ and: >= 13 and <= 19 => "teen". في C# 8 كنت ستسرد القيم كأذرع منفصلة بالنتيجة نفسها.

هل يمكنني استخدام when في تعبير switch في C#؟

نعم. يمكن للذراع إضافة حراسة بعد نمطها: Order o when o.Total > 100 => 0m. لا تطابق الذراع إلا إن طابق النمط وكان شرط when صحيحًا؛ وإلا يستمر التقييم مع الذراع التالية.

هل أستخدم تعبير switch أم جملة switch؟

استخدم التعبير حين لا ينتج كل فرع سوى قيمة، مثل ربط حالة بتسمية أو حساب سعر. واستخدم الجملة حين تنفّذ الفروع عدة عبارات أو لها آثار جانبية أو تحتاج إلى مغادرة حلقة. ويمنحك التعبير أيضًا تحذيرات شمول لا تمنحها الجملة.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن