22. FlagsAttribute

הטיפ האחרון לזמן הקרוב על enumים:

מדי פעם אנחנו יוצרים enum שאנחנו מעוניינים שיהיו אפשרויות של צירוף מספר ערכים מתוכו.

למשל, enum המציין כיוון:

1
2
3
4
5
6
7
8
public enum Direction
{
None,
North,
South,
East,
West
}

נניח כי יש לנו פונקציה אזור, ואנחנו רוצים להעביר לה מספר אזורים. דרך מקובלת לעשות זאת היא כך:

1
2
PrintDirectionData(Direction.West |
Direction.North);

כדי שזה יפעל אנחנו צריכים לדאוג לדברים הבאים:

כל ערך רצוי לקבל בenum הוא חזקה של 2.

ערך של אף אפשרות מקבל את הערך 0.

לדוגמה:

1
2
3
4
5
6
7
8
public enum Direction
{
None = 0,
North = 1,
South = 2,
East = 4,
West = 8
}

כעת כדי לבדוק האם קיבלנו ערך שמכיל אפשרות ספציפית:

1
2
3
4
if ((direction & Direction.South) == Direction.South)
{
// ...
}

הקוד לעיל בודק האם המשתמש שלח אפשרות שמכילה Direction.South.

הסיבה שהדבר הזה עובד היא מכיוון שבבינארית האפשרויות נראות כך:

1
2
3
4
North = 0b0001,
South = 0b0010,
East = 0b0100,
West = 0b1000

(הכתיב הוא בסינטקס של C# 7.0)

וכשמשלבים שני דגלים מקבלים ערך שמופיעה בו "נורה" בדיוק בדגלים ששילבנו. דרך נוחה לבדוק האם "נורה" דולקת היא לעשות AND עם ה"נורה" ולבדוק שקיבלנו את ערך הנורה (או לחלופין לבדוק שקיבלנו ערך שאינו 0).

הכל נראה טוב ויפה, אך ישנה בעיה. שימו לב לקוד הבא:

1
2
3
4
5
6
7
Direction west = Direction.West;
Direction southEast = Direction.South |
Direction.East;
Console.WriteLine(west); // prints West
Console.WriteLine(southEast); //prints 6

שימו לב שהשורה השנייה מדפיסה 6, בניגוד לשורה הראשונה שמדפיסה את שם הenum.

מהסיבה הזו ועוד סיבות דומות, המציאו הAttribute ששמו FlagsAttribute.

אם נשים כעת את הAttribute הזה מעל הenum ונריץ את הקוד, נקבל:

1
2
3
4
5
6
7
Direction west = Direction.West;
Direction southEast = Direction.South |
Direction.East;
Console.WriteLine(west); // prints West
Console.WriteLine(southEast); //prints South, East

הAttribute הזה אומר לFramework שהenum הוא בעצם enum של דגלים ("נורות") ונותן לנו תמיכה מתאימה בכמה פונקציות של enumים.

המשך יום טוב

שתף