יום שני, 5 במרץ 2018

Enum ב-#C

Enum

בעבר למדנו על Enum בשפת C, היום נלמד עליו ב-#C.
Enum מאפשר לנו ליצג במילים דברים שהיינו יכולים ליצג במספרים, למען קריאות התוכנית למתכנת.

- ניתן ליצור Enum בתוך ומחוץ למחלקות ולמבנים. (מבנים = structs).
- פנייה לקבוע של אינם מסויים היא באמצעות שם האינם.
- אם מדובר באינם ציבורי ממחלקה אחרת, ניתן לפנות אליו רק בצירוף שם המחלקה.
- לכל מילה יש ערך מספרי. בברירת המחדל למילה הראשונה יש את הערך 0 ולכל מילה אחריה יש ערך גדול ב-1.
- לא ניתן להוסיף קבועים לEnum במהלך התוכנית.








דוגמאות:


Enum בתוך מחלקה, והמרה מקבוע אל int:
    class Program
    {
        // יצירת אינם ציבורי בתוך מחלקה
        public enum Season { WINTER, SPRING, SUMMER, FALL } 
 
        static void Main(string[] args)
        {
            // לתת למשתנה את הערך המספרי של קבוע מסוים בתוך האינם
            // int שימו לב שבשפת סי שארפ נדרשת המרה ל  
            int x = (int)Season.WINTER;
            int y = (int)Season.SUMMER;
 
            Console.WriteLine("WINTER = {0}", x); // ידפיס 0
            Console.WriteLine("SUMMER = {0}", y); // ידפיס 2
        }
    }







Enum שהקבוע הראשון בו לא מתחיל בערך 0:
    class Program
    {
        // קביעת הערך הראשוני ל-10
        public enum Season { WINTER = 10, SPRING, SUMMER, FALL } 
 
        static void Main(string[] args)
        {
            int x = (int)Season.WINTER;
            int y = (int)Season.SUMMER;
 
            Console.WriteLine("WINTER = {0}", x); // ידפיס 10
            Console.WriteLine("SUMMER = {0}", y); // ידפיס 12
        }
    }





עליכם להיזהר לא לתת את אותו הערך לשני קבועים שונים (אלא אם זה בדיוק מה שאתם רוצים):
    class Program
    {
        // יהיה גם הוא 10 SUMMER
        public enum Season { WINTER = 10, SPRING = 9, SUMMER, FALL } 
 
        static void Main(string[] args)
        {
            int x = (int)Season.WINTER;
            int y = (int)Season.SUMMER;
 
            Console.WriteLine("WINTER = {0}", x); // ידפיס 10
            Console.WriteLine("SUMMER = {0}", y); // ידפיס 10
        }
    }







גישה אל Enum ציבורי ממחלקה אחרת:
    class TimeAndMore
    {
        public enum Season { WINTER, SPRING, SUMMER, FALL } 
 
 
    }
    class Program
    {
        static void Main(string[] args)
        {
            // פנייה לאינם ממחלקה אחרת
            int x = (int)TimeAndMore.Season.WINTER;
            int y = (int)TimeAndMore.Season.SUMMER;
 
            Console.WriteLine("WINTER = {0}", x); // ידפיס 0
            Console.WriteLine("SUMMER = {0}", y); // ידפיס 2
        }
    }






גישה אל Enum גלובאלי:
    enum Season { WINTER, SPRING, SUMMER, FALL } 
    class Program
    {
        static void Main(string[] args)
        {
            // פנייה לאינם גלובאלי
            int x = (int)Season.WINTER;
            int y = (int)Season.SUMMER;
 
            Console.WriteLine("WINTER = {0}", x); // ידפיס 0
            Console.WriteLine("SUMMER = {0}", y); // ידפיס 2
        }
    }






הפונקציה GetNames מחזירה מערך של שמות כל הקבועים באינם.
    class Program
    {
        enum Season { WINTER, SPRING, SUMMER, FALL }
        static void Main(string[] args)
        {
            // אפשרות א' להדפסת שמות כל הקבועים באינם
            foreach (string s in Enum.GetNames(typeof(Season)))
            {
                Console.WriteLine(s);
            }
            // :ידפיס
            //WINTER
            //SPRING
            //SUMMER
            //FALL
 
 
 
            // אפשרות ב' להדפסת שמות כל הקבועים באינם
            for (int i = 0; i < Enum.GetNames(typeof(Season)).Length; i++)
            {
                Console.WriteLine(Enum.GetNames(typeof(Season))[i]);
            }
            // :ידפיס
            //WINTER
            //SPRING
            //SUMMER
            //FALL
 
 
 
            // אפשרות ג' (שדומה לב') להדפסת שמות כל הקבועים באינם
            String[] StringArray = Enum.GetNames(typeof(Season));
            for (int i = 0; i < StringArray.Length; i++)
            {
                Console.WriteLine(StringArray[i]);
            }
            // :ידפיס
            //WINTER
            //SPRING
            //SUMMER
            //FALL
        }
    }





שימו לב שהפונקציה GetNames ממיינת את המערך על פי הערך של הקבועים.
ראשית את כל הערכים שערכם גדול או שווה אפס - מהקטן לגדול.
ואז את כל הערכים שערכם קטן מאפס - מהקטן לגדול.
ערכים זהים יופיעו לפי הסדר המקורי.
כך:
    class Program
    {
        enum ABC { A = 7, B = -4, C = -3, D = 8, E = 0, F = 7, G = -10}
        static void Main(string[] args)
        {
            foreach (string s in Enum.GetNames(typeof(ABC)))
            {
                Console.WriteLine(s);
            }
            // :ידפיס ללא הסוגריים
            //E  (0)
            //A  (7)
            //F  (7)
            //D  (8)
            //G  (-10)
            //B  (-4)
            //C  (-3)
        }
    }






הפונקציה GetValues מחזירה מערך של כל הקבועים באינם.
שימו לב שהפונקציה ממיינת את המערך על פי הערך של הקבועים, באותו אופן ש-GetNames ממיינת.
אבל: אם יש קבועים בעלי ערכים זהים - הקבוע הראשון יופיע מספר פעמים במערך, ושאר הקבועים הזהים לו לא יופיעו. (בשונה מ-GetNames).
כך:
    class Program
    {
        enum ABC { A = 7, B = -4, C = -3, D = 8, E = 0, F = 7, G = -10 }
        static void Main(string[] args)
        {
            foreach (ABC s in Enum.GetValues(typeof(ABC)))
            {
                Console.WriteLine(s);
            }
            // :ידפיס ללא הסוגריים
            //E  (0)
            //A  (7)
            //A  (7)   // A מכיל פעמיים את
            //D  (8)
            //G  (-10)
            //B  (-4)
            //C  (-3)
 
 
            // int המרה אוטומטית ל
            foreach (int n in Enum.GetValues(typeof(ABC)))
            {
                Console.WriteLine(n);
            }
            // :ידפיס
            //0
            //7
            //7
            //8
            //-10
            //-4
            //-3
        }
    }







CompareTo(target)
הפונקציה משווה את האובייקט הנוכחי ל-target.
- אם target גדול: מחזירה ערך שקטן מ-0.
- אם target קטן: מחזירה ערך שגדול מ-0.
- אם זהים: מחזירה 0.
כך:
    class Program
    {
        enum ABC { A = 0, B = 1, C = 2, D = 0}
        static void Main(string[] args)
        {
            ABC Char1 = ABC.A, Char2 = ABC.B, Char3 = ABC.C, Char4 = ABC.D;
            if (Char1.CompareTo(Char2) < 0) Console.WriteLine("1. Char2 Big");
            if (Char2.CompareTo(Char3) < 0) Console.WriteLine("2. Char3 Big");
            if (Char1.CompareTo(Char4) == 0) Console.WriteLine("3. Char1 == Char4");
            // :ידפיס
            //1. Char2 Big
            //2. Char3 Big
            //3. Char1 == Char4
        }
    }





הפיכה של מספר לאובייקט Enum המקביל אליו בערכו:
    class Program
    {
        enum ABC { A = 0, B = 1, C = 2, D = 3, E = 9, F = 0 }
        static void Main(string[] args)
        {
            int number1 = 0, number2 = 9;
            ABC Char1, Char2;
            Char1 = (ABC)ABC.ToObject(typeof(ABC), number1);
            Char2 = (ABC)ABC.ToObject(typeof(ABC), number2);
            Console.WriteLine(Char1); // A
            Console.WriteLine(Char2); // E
        }
    }





בדוגמה הקודמת הפכנו מספר לאובייקט של Enum.
אבל מה אם הערך הזה בכלל לא היה קיים באינם שלנו? -לא נעים.
לשם כך באפשרותנו לבדוק האם הערך קיים באינם על ידי הפונקציה IsDefined, ורק אחר כך להשתמש בו.
כך:
    class Program
    {
        enum ABC { A = 0, B = 1, C = 2, D = 3, E = 9, F = 0 }
        static void Main(string[] args)
        {
            int number1 = 0, number2 = 10;
            ABC Char1 = ABC.B, Char2 = ABC.B;
 
            if (Enum.IsDefined(typeof(ABC), number1))
                Char1 = (ABC)ABC.ToObject(typeof(ABC), number1);
            if (Enum.IsDefined(typeof(ABC), number2))
                Char2 = (ABC)ABC.ToObject(typeof(ABC), number2);
 
            Console.WriteLine(Char1); // A
            Console.WriteLine(Char2); // B
        }
    }








באותו אופן אפשר להפוך מחרוזת לאובייקט Enum, על ידי הפונקציה Parse או TryParse.
המחרוזת יכולה להיות שם הקבוע או הערך שלו.
דוגמה 1:
    class Program
    {
        public enum ABC { Unknown = -3, A = 0, B, C, D, E, F };
        static void Main(string[] args)
        {
            string StringNumber1 = "1";
            string StringNumber2 = "-1";
            string name = "F";
 
            ABC status1 = ABC.Unknown;
            ABC status2 = ABC.Unknown;
            ABC status3 = ABC.Unknown;
            
 
            //   לא יודעת לזהות מחרוזת שזהה לערך קיים IsDefined הקוד הזה לא אפשרי משום שהפונקציה 
            // היא יודעת רק לזהות ערך מספרי קיים או מחרוזת שם קיים או אובייקט אינם תקין
            //if (Enum.IsDefined(typeof(ABC), StringNumber))
            //    status1 = (ABC)Enum.Parse(typeof(ABC), StringNumber);
 
 
            status1 = (ABC)Enum.Parse(typeof(ABC), StringNumber1);
            if (!Enum.IsDefined(typeof(ABC), status1))
                status1 = ABC.Unknown;
 
            status2 = (ABC)Enum.Parse(typeof(ABC), StringNumber2);
            if (!Enum.IsDefined(typeof(ABC), status2))
                status2 = ABC.Unknown;
 
            if (Enum.IsDefined(typeof(ABC), name))
                status3 = (ABC)Enum.Parse(typeof(ABC), name);
 
            Console.WriteLine("Converted '{0}' to {1}", StringNumber1, status1);
            Console.WriteLine("Converted '{0}' to {1}", StringNumber2, status2);
            Console.WriteLine("Converted '{0}' to {1}", name, status3);
 
            // :ידפיס
            //Converted '1' to B
            //Converted '-1' to Unknown
            //Converted 'F' to F
        }
    }





דוגמה 2:
    class Program
    {
        public enum ArrivalStatus { Unknown = -3, Late = -1, OnTime = 0, Early = 1 };
        static void Main(string[] args)
        {
            string number = "-1";
            string name = "Early";
 
 
            ArrivalStatus status1 = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), number);
 
            // אם לא קיים כזה ערך או שם
            if (!(Enum.IsDefined(typeof(ArrivalStatus), status1)))
                status1 = ArrivalStatus.Unknown;
            Console.WriteLine("Converted '{0}' to {1}", number, status1);
            
 
            ArrivalStatus status2;
            if (Enum.TryParse<ArrivalStatus>(name, out status2))
            {
                if (!(Enum.IsDefined(typeof(ArrivalStatus), status2)))
                    status2 = ArrivalStatus.Unknown;
                Console.WriteLine("Converted '{0}' to {1}", name, status2);
            }
            else
            {
                Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
                                  number);
            }
 
            // :ידפיס
            //       Converted '-1' to Late
            //       Converted 'Early' to Early
        }
    }






הקוד הבא מראה איך לראות ולהדפיס את הטייפ, והטייפ הבסיסי של Enum:
    class Program
    {
        public static void Main()
        {
            Enum[] enumValues = { ConsoleColor.Red, DayOfWeek.Monday, 
                            MidpointRounding.ToEven, PlatformID.Win32NT, 
                            DateTimeKind.Utc, StringComparison.Ordinal };
 
            Console.WriteLine("{0,-10} {1, 18}   {2,15}\n",
                              "Member""Enumeration""Underlying Type");
 
            foreach (var enumValue in enumValues)
                DisplayEnumInfo(enumValue);
        }
 
        static void DisplayEnumInfo(Enum enumValue)
        {
            Type enumType = enumValue.GetType();
            Type underlyingType = Enum.GetUnderlyingType(enumType);
            Console.WriteLine("{0,-10} {1, 18}   {2,15}",
                              enumValue, enumType.Name, underlyingType.Name);
        }
    }
    // :הדפסה
    //       Member            Enumeration   Underlying Type
    //       
    //       Red              ConsoleColor             Int32
    //       Monday              DayOfWeek             Int32
    //       ToEven       MidpointRounding             Int32
    //       Win32NT            PlatformID             Int32
    //       Utc              DateTimeKind             Int32
    //       Ordinal      StringComparison             Int32










בהצלחה.

אין תגובות:

הוסף רשומת תגובה