כמה הבהרות לגבי הקריאות ל-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) { }