חוקי קריאה ל-base


הבהרות base

כמה הבהרות לגבי הקריאות ל-base ל- base: ול- this:

מגבלות על קריאה לבנאי של מחלקת האב

1. ניתן לקרוא רק מתוך בנאי של מחלקת הבן

ניתן לקרוא לבנאי של מחלקת האב רק באמצעות התחביר (...)base:, ורק מתוך בנאי של מחלקת הבן - לעולם לא מתוך מתודה רגילה.

2. חייב להופיע בחתימת הבנאי

הקריאה (...)base: חייבת להופיע בשורת ההגדרה של הבנאי, לא בתוך גוף הבנאי:

class P
{
    public P(int x) { }
}

class C : P
{
    // ✅ נכון - בחתימת הבנאי
    public C(int x) : base(x)
    {
        // גוף הבנאי
    }
    
    // ❌ שגוי - לא ניתן לקרוא בתוך הגוף
    public C(int x)
    {
        base(x); // זה לא יקומפל!
    }
}

3. קריאה אוטומטית אם לא צוין במפורש

אם לא קוראים במפורש ל-(...)base:, C# אוטומטית קורא לבנאי ללא פרמטרים של מחלקת האב:

class P
{
    public P() { } // בנאי ללא פרמטרים
}

class C : P
{
    public C() // קורא באופן סמוי ל-base()
    {
    }
}

4. חובה לקרוא במפורש אם אין בנאי ללא פרמטרים באב

אם למחלקת האב אין בנאי ללא פרמטרים, חובה לקרוא לאחד מהבנאים במפורש:

class P
{
    public P(int x) { } // רק בנאי עם פרמטרים
    // אין בנאי ללא פרמטרים!
}

class C : P
{
    // ❌ אין בנאי ללא פרמטרים ⟵ לא יתקמפל P -ל
    public C()
    {
    }
    
    // ✅ חובה לקרוא ל-base במפורש
    public C(int x) : base(x)
    {
    }
}

5. ניתן לקרוא רק לבנאי אחד של האב

לא ניתן לשרשר מספר בנאים של האב - רק (...)base: אחד לכל בנאי של הבן.

6. בנאי האב רץ לפני גוף הבנאי של הבן

בנאי האב תמיד מתבצע לפני כל קוד בגוף הבנאי של הבן.


הבדל חשוב: קריאה למתודות של האב

חשוב להבחין: המגבלות לעיל חלות רק על קריאה לבנאים של מחלקת האב באמצעות (...)base:.

לעומת זאת, קריאה למתודות רגילות של מחלקת האב באמצעות ()base.MethodName ניתנת לביצוע מכל מתודה, בכל עת, ללא מגבלות (למעט מתודות static):

class P
{
    public virtual void DoSomething() { }
}

class C : P
{
    public override void DoSomething()
    {
        base.DoSomething(); // ✅ עובד מצוין
    }
    
    public void AnyOtherMethod()
    {
        base.DoSomething(); // ✅ גם כאן עובד
    }
}

לסיכום:

  • (...)base: - רק בחתימת בנאי, קריאה לבנאי האב
  • ()base.MethodName - מכל מקום, קריאה למתודות/תכונות של האב

שרשור בנאים באותה מחלקה - (...)this:

בדומה ל-(...)base:, ניתן להשתמש ב-(...)this: כדי לקרוא לבנאי אחר באותה מחלקה:

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    // בנאי מלא
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    // בנאי שקורא לבנאי אחר באותה מחלקה
    public Person(string name) : this(name, 0)
    {
        // ניתן להוסיף לוגיקה נוספת כאן
    }
    
    // בנאי ברירת מחדל
    public Person() : this("Unknown")
    {
    }
}

מה ההבדל בין this: ל-base:?

  • (...)this: - קורא לבנאי אחר באותה מחלקה
  • (...)base: - קורא לבנאי במחלקת האב

יתרונות

  • הימנעות מכפילות קוד - הלוגיקה המרכזית נמצאת בבנאי אחד
  • תחזוקה קלה יותר - שינויים נעשים במקום אחד

מגבלה חשובה

לא ניתן להשתמש גם ב-:this וגם ב-:base באותו בנאי - רק אחד מהם!

// ❌ שגוי - לא ניתן לשלב
public C(int x) : base(x), this(x) { }

// ✅ נכון - רק אחד
public C(int x) : this(x, 0) { }