# Enums📖 שיעור

## מה זה?

איך הייתם מייצגים סטטוס הזמנה — "ממתין", "נשלח", "בוטל"? אפשרות אחת: מספר (`status = 1`) — אבל מה זה `1`? צריך לזכור מיפוי בראש. אפשרות שנייה: מחרוזת (`status = "Pending"`) — אבל אפשר בטעות לכתוב `"pending"` (אות קטנה) או `"Pendign"` (שגיאת כתיב), וה-Compiler לא יתפוס את זה. `enum` פותר את שתי הבעיות: קבוצת שמות קבועה וסגורה, עם בדיקת טיפוסים מלאה בזמן קומפילציה.

## מילות מפתח שחשוב לזכור

• `enum` — טיפוס שמגדיר קבוצה סגורה וקבועה של ערכים אפשריים, כל אחד עם שם ברור

• Underlying Value — כל ערך ב-`enum` מיוצג פנימית כמספר שלם (`int` כברירת מחדל), מתחיל מ-0

• Magic Number — מספר "חסר הקשר" בקוד (כמו `status == 1`) שקשה להבין בלי לחפש הגדרה

```csharp
enum OrderStatus
{
    Pending,    // = 0 (default)
    Shipped,    // = 1
    Delivered,  // = 2
    Cancelled   // = 3
}

OrderStatus status = OrderStatus.Pending;

if (status == OrderStatus.Shipped)
{
    Console.WriteLine("Order shipped");
}
```

```csharp
// switch on enum — readable and organized, and C# warns if you forget a case
string DescribeStatus(OrderStatus status) => status switch
{
    OrderStatus.Pending => "Awaiting processing",
    OrderStatus.Shipped => "On its way to you",
    OrderStatus.Delivered => "Delivered successfully",
    OrderStatus.Cancelled => "Cancelled",
    _ => "Unknown status"
};
```

## הסבר עיקרי

`enum` מול Magic Number — `if (status == 1)` דורש שמישהו יזכור (או יחפש בתיעוד) ש-`1` פירושו "נשלח". `if (status == OrderStatus.Shipped)` קריא ומתעד את עצמו — אין צורך לזכור מיפוי מספרים. זו בדיוק אותה סיבה ש-`const`/שמות ברורים עדיפים על ערכים גולמיים — כאן זה מורחב לקבוצת ערכים שלמה.

למה `enum` עדיף על מחרוזת חופשית — עם `string status = "Pending"`, שום דבר לא מונע `status = "pendingg"` (שגיאת הקלדה) — הקוד יתקמפל, והבאג יתגלה רק בזמן ריצה, אם בכלל. עם `enum`, `OrderStatus.Pendingg` פשוט **לא מתקמפל** — הקומפיילר בודק שהערך קיים בקבוצה הסגורה.

הערך המספרי מאחורי הקלעים — לכל איבר ב-`enum` יש ערך `int` מוצמד, שמתחיל מ-0 וגדל אוטומטית (אלא אם קובעים אחרת במפורש). זה שימושי לדעת, אבל ברוב הקוד עובדים עם השם (`OrderStatus.Shipped`), לא עם המספר — המספר הוא פרט מימוש פנימי.

## יתרונות

מונע שגיאות הקלדה שקיימות במחרוזות חופשיות — הקומפיילר בודק את הערך; קוד קריא בהרבה מהשוואה למספרי-קסם; `switch` על `enum` מזהיר אם שכחתם לטפל במקרה קיים, מה שתופס באגים מוקדם.

## חסרונות

הוספת ערך חדש ל-`enum` קיים דורשת לעדכן את כל מקומות ה-`switch` שמטפלים בו (אבל זו בדיוק ההגנה — עדיף לגלות את זה בקומפילציה מאשר בפרודקשן); `enum` לא מתאים לערכים שיכולים להשתנות דינמית בזמן ריצה (למשל רשימת קטגוריות שמנוהלת ב-DB).

## נקודות חשובות

• `enum` = קבוצת ערכים סגורה וקבועה, נבדקת בזמן קומפילציה

• לכל ערך יש `int` מוצמד שמתחיל מ-0 כברירת מחדל

• `enum` עדיף על Magic Numbers ומחרוזות חופשיות לייצוג קבוצת אפשרויות קבועה

• `switch` על `enum` הוא שימוש נפוץ במיוחד — קריא ובטוח

## טעויות נפוצות

• להשתמש במחרוזת חופשית ("Pending") לייצוג סטטוס במקום `enum` — פתוח לשגיאות הקלדה

• לשכוח לטפל בכל הערכים האפשריים ב-`switch` על `enum` (למרות שה-Compiler בדרך כלל יתריע)

• להסתמך על הערך המספרי של `enum` (`(int)status == 1`) במקום על השם — פחות קריא ושביר יותר לשינויים

## סיכום

`enum` מייצג קבוצת אפשרויות קבועה וסגורה עם שמות ברורים, ופותר את בעיית ה-Magic Numbers והמחרוזות החופשיות הפגיעות לשגיאות הקלדה. כל ערך מוצמד למספר `int` פנימי, אך בקוד עובדים עם השם — קריא, בטוח, ונבדק בזמן קומפילציה בדיוק כמו כל טיפוס אחר ב-C#.

## דוקומנטציה רשמית

[Microsoft Learn — Enumeration types](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/enum)

---

## תרגילים

### תרגיל 1 — enum ראשון

**המשימה:** הגדירו `enum DayOfWeek` עם שבעת ימות השבוע, וכתבו קוד שמדפיס האם היום הנוכחי (בחרו ערך קבוע לדוגמה) הוא יום עבודה או סוף שבוע.

**בדיקה:** `DayOfWeek.Friday` או `DayOfWeek.Saturday` מדפיסים "סוף שבוע"; כל יום אחר מדפיס "יום עבודה".

### תרגיל 2 — switch על enum

**המשימה:** הגדירו `enum TrafficLight { Red, Yellow, Green }`, וכתבו `switch expression` שמחזיר הוראה מתאימה לכל צבע ("עצור", "היכון", "סע").

**בדיקה:** `TrafficLight.Red` מחזיר `"עצור"`; `TrafficLight.Green` מחזיר `"סע"`.

---

## פרויקט מסכם

**המשימה:** כתבו תוכנית ניהול הזמנות פשוטה עם `enum OrderStatus { Pending, Shipped, Delivered, Cancelled }`.

**דרישות:**
1. פונקציה `AdvanceStatus(OrderStatus current)` שמחזירה את הסטטוס הבא בתהליך (Pending→Shipped→Delivered), ומחזירה `Cancelled` ללא שינוי אם ההזמנה כבר בוטלה
2. פונקציה `DescribeStatus` (כמו בדוגמה) שמתרגמת כל סטטוס למשפט בעברית
3. ב-`Main`, הדגימו התקדמות מלאה של הזמנה אחת מ-`Pending` עד `Delivered`, עם הדפסת התיאור אחרי כל שלב

**בדיקה:** הפעלת `AdvanceStatus` שלוש פעמים ברצף על הזמנה חדשה מגיעה בדיוק ל-`Delivered`; קריאה נוספת על הזמנה `Cancelled` לא משנה את הסטטוס.

## מה בפרק הבא

בפרק הבא — **Value מול Reference, ו-`out`**: מה קורה בפועל כשמעבירים משתנה לפונקציה — האם היא מקבלת עותק, או גישה למשתנה המקורי?
