משתנים וטיפוסים
מה זה?
בשפות דינמיות (כמו JavaScript או Python) אפשר לכתוב x = 5 ואז x = "hello" באותו משתנה בלי שאף אחד יתלונן — עד שבמקום לא צפוי בזמן ריצה, הקוד מנסה לחבר מספר למחרוזת ומתרסק. C# פותרת את זה עם Strong Static Typing: לכל משתנה יש טיפוס קבוע שנקבע בזמן קומפילציה, וניסיון להכניס אליו ערך מהטיפוס הלא נכון נתפס לפני שהתוכנית בכלל רצה — לא בפרודקשן, אצל משתמש אמיתי.
מילות מפתח שחשוב לזכור
• Literal — ערך קבוע כתוב ישירות בקוד (5, "שלום", true)
• Static Typing — טיפוס המשתנה נקבע ונבדק בזמן קומפילציה, לא בזמן ריצה
• var — הצהרה עם טיפוס משתמע; C# עדיין קובעת את הטיפוס בקומפילציה לפי הערך הראשוני — זה לא דינמי
• Primitive Types — טיפוסים בסיסיים כמו int, double, bool, char, שמייצגים ערך יחיד ישירות
• Reference/Object Types — טיפוסים כמו string או מחלקות מותאמות-אישית, שמחזיקים הפניה לאובייקט
int age = 25; // primitive — whole number
double price = 19.99; // primitive — decimal number
bool isActive = true; // primitive — true/false
char grade = 'A'; // primitive — single character
string name = "Dana"; // reference type — object
var score = 100; // C# infers: score is int, and stays int forever
// score = "high"; // compilation error — CS0029: cannot convert string to int
flowchart TD
A["int age = 25;"] --> B{"Trying: age = 'text';"}
B -->|"C# — Static Typing"| C["Compilation error<br/>immediately, before running"]
הסבר עיקרי
var הוא לא “טיפוס דינמי” — var רק אומר לקומפיילר “תסיק את הטיפוס בעצמך לפי הערך הראשוני”. ברגע שהוא הוסק (var score = 100; → score הוא int), הוא קבוע לכל אורך חיי המשתנה, בדיוק כמו לוּ נכתב int score = 100; במפורש. זה שונה לגמרי מ-JavaScript, שם let x יכול להחזיק כל טיפוס בכל רגע.
Primitive מול Object — טיפוסים פרימיטיביים (int, double, bool, char) מחזיקים את הערך עצמו ישירות; טיפוסי Object/Reference (string, מחלקות) מחזיקים הפניה (reference) לאובייקט שמאוחסן בנפרד. ההבדל הזה יהיה קריטי בהמשך כשנדבר על Value מול Reference בהעברת פרמטרים לפונקציות — כאן מספיק לזכור שהם מתנהגים אחרת.
זמן קומפילציה מול זמן ריצה — הבדיקה של C# קורית כשמריצים dotnet build, לא כשהתוכנית באמת רצה אצל משתמש. זו הסיבה שבפיתוח ב-C# מגלים שגיאות טיפוסים מוקדם בהרבה — לפני שהקוד בכלל הגיע לבדיקה, ובטח לפני production.
יתרונות
שגיאות טיפוסים נתפסות בזמן קומפילציה, לפני שהקוד רץ בכלל — לא כ"הפתעה" בפרודקשן; IDE יודע להציע Autocomplete מדויק כי הוא יודע בוודאות מה הטיפוס של כל משתנה; קוד עם טיפוסים מפורשים קריא יותר — רואים מיד מה כל משתנה אמור להכיל.
חסרונות
צריך להצהיר על טיפוסים (או לפחות לתת לקומפיילר להסיק אותם) — יותר “טקסט” מקוד בשפה דינמית; לפעמים הטיפוס הנכון לא ברור מראש וצריך refactor אם משנים כיוון (למשל שדה שהיה int וצריך שיהיה double).
נקודות חשובות
• Static Typing = טיפוסים נבדקים בזמן קומפילציה; Dynamic Typing = נבדקים בזמן ריצה
• var לא הופך את C# לדינמית — הטיפוס עדיין נקבע בקומפילציה, רק מוסק אוטומטית
• טיפוסים פרימיטיביים מחזיקים ערך ישירות; טיפוסי Object/Reference מחזיקים הפניה
• string הוא reference type, למרות שמתנהג בהרבה מקומות “כמו” ערך פשוט
טעויות נפוצות
• לחשוב ש-var הופך משתנה לגמיש כמו ב-JavaScript — הוא לא, הטיפוס קבוע מרגע ההסקה
• לנסות להשוות int ל-string ישירות ולהתפלא משגיאת קומפילציה
• לבלבל בין הצהרת טיפוס (int age;) לאתחול ערך (age = 25;) — אפשר להצהיר בלי לאתחל, אבל לא להשתמש בערך לפני שהוא מאותחל
סיכום
C# היא שפה עם Strong Static Typing — כל משתנה מקבל טיפוס קבוע שנבדק כבר בזמן קומפילציה, מה שתופס שגיאות סוג לפני שהתוכנית בכלל רצה. var הוא נוחות תחבירית להסקת טיפוס, לא מעבר לטיפוסיות דינמית. ההבחנה בין טיפוסים פרימיטיביים (ערך ישיר) לטיפוסי Object/Reference (הפניה לאובייקט) היא יסוד שיחזור וישפיע על נושאים מתקדמים יותר בהמשך.
דוקומנטציה רשמית
Microsoft Learn — Built-in types
תרגילים
תרגיל 1 — טיפוסים בסיסיים
המשימה: הצהירו על 5 משתנים: int, double, bool, char, string, כל אחד עם ערך מתאים, והדפיסו את כולם עם Console.WriteLine.
בדיקה: התוכנית מתקמפלת ומדפיסה 5 שורות, כל אחת עם הערך והטיפוס הנכונים.
תרגיל 2 — שגיאת קומפילציה מכוונת
המשימה: כתבו int number = 10; ואז נסו להריץ number = "text";. תעדו את הודעת השגיאה שהקומפיילר מציג.
בדיקה: הקוד לא מתקמפל; הודעת השגיאה מזכירה שלא ניתן להמיר string ל-int (CS0029).
פרויקט מסכם
המשימה: כתבו תוכנית “כרטיס ביקור” שמאחסנת פרטי אדם ומדפיסה אותם בפורמט קריא.
דרישות:
- משתנים:
name(string),age(int),heightMeters(double),isStudent(bool) - לפחות משתנה אחד מוצהר עם
var(עם הסקת טיפוס) - הדפסה של כל הפרטים במשפט אחד מלא, לדוגמה:
"דנה, בת 25, גובה 1.7 מ', סטודנטית: כן"
בדיקה: התוכנית מתקמפלת ללא שגיאות, ומדפיסה את כל הפרטים בפורמט קריא ומדויק.
מה בפרק הבא
בפרק הבא — קלט/פלט בסיסי: איך מקבלים מהמשתמש קלט עם Console.ReadLine, ולמה תמיד צריך להמיר אותו במפורש מ-string לטיפוס הרצוי.