מבנה בר איפוס? (או בעברית, Nullable Struct) + האופרטור (הסודי) ??
לאחרונה יצא לי להתקל במצב שהייתי צריך להשתמש ב - Struct שיכול להיות null (כמובן שאפשר לעבור ל - class, אבל זו לא הנקודה), על מנת שאוכל לדעת האם הוא מאותחל.
נניח ויש לנו את ה - struct הבא:
public struct NiceStruct
{
public NiceStruct(int _NiceInt, string _NiceString)
{
this._NiceInt = _NiceInt;
this._NiceString = _NiceString;
}
private readonly int _NiceInt;
private readonly string _NiceString;
public int NiceInt
{
get { return _NiceInt; }
}
public string NiceString
{
get { return _NiceString; }
}
}
לא ניתן ליצור מופע של ה - struct שהוא null (מכיוון שטיפוסים שהם Value Type מאותחלים אוטומטית עם הכרזתם, ללא צורך לקרוא ל - constructor, ניתן לקרוא עוד על ההבדלים בין struct ל - class בפוסט של ג'סטין). ברגע שנצהיר על אובייקט מסוג NiceStruct, ה - int יאותחל אוטומטית ויכיל את הערך 0, וה - string יאותחל למחרוזת ריקה. אם ננסה להציב null, נקבל שגיאת קומפילציה.
אז איך מגדירים struct (להלן "המבנה"), שיכול להיות null (להלן "בר איפוס")?
ב - .NET 2.0 מיקרוסופט הציגו את Nullable<T>, (רובכם מכירים את ה - ? שבא אחרי type כלשהו כמו int). ה - Nullable הוא מאוד פשוט:
struct Nullable<T>
{
public bool HasValue;
public T Value;
}
בעזרתו ניתן להגדיר מבנה שיכול להיות בר איפוס, בשני אופנים:
NiceStruct? myNiceStruct;
Nullable<NiceStruct> myOtherNiceStruct;
כעת ניתן לבדוק האם myNiceStruct או myOtherNiceStruct מאותחלים גם בשני אופנים:
1: if (myNiceStruct != null)
2: if (myNiceStruct.HasValue)
בכדי לגשת למתודות או למאפיינים (Properties) של מופע מסויים, יש לגשת ל - Value, לדוגמה - הדפסה של NiceString תראה כך:
Console.WriteLine(myNiceStruct.Value.NiceString);
.csharpcode .lnum { color: #606060; }
ועכשיו תוספת קטנה, האופרטור ?? (הא?
)
אישית, לא ידעתי על האופרטור הזה, עד לפני מספר חודשים, וגם די התפלאתי לשמוע עליו, האופרטור הזה בודק עם ערך מסויים (שבא לפני האופרטור) הוא null, ומחזיר את הערך במידה והוא לא null, אחרת הוא מחזיר את מה שאחרי האופרטור. לא מובן בכלל הא? שורת קוד אחת תסביר לכם:
myOtherNiceStruct = myNiceStruct ?? new NiceStruct(10, "Some text");
הקוד הזה בעצם, בודק אם myNiceStruct אינו null, אם הוא מלא, myNiceStruct יוצב ב - myOtherNiceStruct, אחרת, myOtherNiceStruct יאותחל עם הערכים 10 ו - "Some text".
עד כאן.