Τι είναι τα Enums (Enumerations) στην C#;

Τα enums είναι ένας τύπος δεδομένων στην C# που σου επιτρέπει να ορίσεις σύνολα σταθερών τιμών με συγκεκριμένα ονόματα. Σκεφτείτε το σαν έναν τρόπο να ομαδοποιήσεις σχετικές σταθερές, δίνοντάς τους φιλικά ονόματα αντί να χρησιμοποιείς απλά αριθμητικές τιμές.

Χαρακτηριστικά των Enums:

  • Οι τιμές του enum είναι συνήθως ακέραιοι αριθμοί, αλλά χρησιμοποιούμε περιγραφικά ονόματα για ευκολότερη κατανόηση και ανάγνωση του κώδικα.
  • Το πρώτο στοιχείο στο enum έχει από προεπιλογή την τιμή 0, το δεύτερο 1 και ούτω καθεξής, εκτός αν ορίσεις διαφορετικές τιμές.

Παράδειγμα χρήσης enum:

Ας υποθέσουμε ότι θέλουμε να αποθηκεύσουμε τις ημέρες της εβδομάδας. Αντί να χρησιμοποιούμε ακέραιους αριθμούς (0 για Δευτέρα, 1 για Τρίτη κ.λπ.), μπορούμε να ορίσουμε ένα enum:

public enum DaysOfWeek
{
Monday, // 0
Tuesday, // 1
Wednesday, // 2
Thursday, // 3
Friday, // 4
Saturday, // 5
Sunday // 6
}

Τώρα μπορούμε να χρησιμοποιούμε το enum μας έτσι:

DaysOfWeek today = DaysOfWeek.Monday;
Console.WriteLine(today); // Εκτυπώνει “Monday”

Μπορούμε επίσης να μετατρέψουμε το enum σε ακέραια τιμή αν θέλουμε:

int dayValue = (int)DaysOfWeek.Monday;
Console.WriteLine(dayValue); // Εκτυπώνει “0”

Ορισμός συγκεκριμένων τιμών στο enum:

Αν θέλουμε να ελέγξουμε τις αριθμητικές τιμές, μπορούμε να τις ορίσουμε ρητά:

public enum DaysOfWeek
{
Monday = 1, // 1
Tuesday = 2, // 2
Wednesday = 3, // 3
Thursday = 4, // 4
Friday = 5, // 5
Saturday = 6, // 6
Sunday = 7 // 7
}

Τώρα, το Monday ξεκινά από το 1 αντί για το 0.

Πλεονεκτήματα χρήσης των Enums:

  1. Αναγνωσιμότητα: Τα ονόματα των τιμών είναι πιο κατανοητά από τυχαίες αριθμητικές τιμές.
  2. Αποφυγή λαθών: Με τα enum, είναι λιγότερο πιθανό να εισαχθούν λανθασμένες αριθμητικές τιμές.
  3. Συντήρηση: Αν χρειαστεί να αλλάξουν οι τιμές, το κάνεις μόνο στο enum και όχι σε όλο τον κώδικα.

υπάρχουν κάποιες επιπλέον λεπτομέρειες και πιο προχωρημένες χρήσεις των enum στην C# που μπορεί να σου φανούν χρήσιμες. Ας εξετάσουμε μερικά πιο εξειδικευμένα χαρακτηριστικά:

1. Ορισμός προσαρμοσμένων τιμών σε enum

Όπως ανέφερα προηγουμένως, μπορείς να ορίσεις συγκεκριμένες αριθμητικές τιμές για κάθε στοιχείο ενός enum. Αυτό είναι χρήσιμο αν χρειάζεσαι οι τιμές να έχουν συγκεκριμένα νοήματα ή να αντιστοιχούν σε άλλες συμβάσεις.

public enum ErrorCode
{
NotFound = 404,
Unauthorized = 401,
InternalServerError = 500
}

ErrorCode code = ErrorCode.NotFound;
Console.WriteLine((int)code); // Εκτυπώνει “404”

2. Συνδυασμός τιμών σε enum με Flags

Ένα ενδιαφέρον χαρακτηριστικό των enum είναι ότι μπορούν να χρησιμοποιηθούν για τον συνδυασμό τιμών μέσω δυαδικών πράξεων. Για αυτό χρησιμοποιείς τη διακόσμηση [Flags] πάνω από το enum, ώστε να μπορείς να συνδυάσεις πολλές τιμές μαζί με χρήση του bitwise OR (|).

Παράδειγμα:

Ας υποθέσουμε ότι έχεις ένα σύνολο δικαιωμάτων πρόσβασης και θέλεις να συνδυάσεις πολλαπλά δικαιώματα:

[Flags]
public enum AccessRights
{
Read = 1, // 001
Write = 2, // 010
Execute = 4 // 100
}

Τώρα μπορείς να συνδυάσεις τα δικαιώματα:

AccessRights rights = AccessRights.Read | AccessRights.Write;
Console.WriteLine(rights); // Εκτυπώνει “Read, Write”

Μπορείς επίσης να ελέγξεις αν έχεις συγκεκριμένο δικαίωμα χρησιμοποιώντας bitwise AND (&):

bool canRead = (rights & AccessRights.Read) == AccessRights.Read;
Console.WriteLine(canRead); // Εκτυπώνει “True”

3. Μετατροπή enum από και προς string

Μπορείς να μετατρέψεις ένα enum σε συμβολοσειρά και το αντίστροφο με τις μεθόδους Enum.ToString() και Enum.Parse() αντίστοιχα.

Μετατροπή από enum σε string:

DaysOfWeek day = DaysOfWeek.Monday;
string dayName = day.ToString();
Console.WriteLine(dayName); // Εκτυπώνει “Monday”

Μετατροπή από string σε enum:

Χρησιμοποιείς τη μέθοδο Enum.Parse() ή Enum.TryParse() αν θέλεις να είσαι ασφαλής από λάθη.

string dayName = “Tuesday”;
DaysOfWeek day = (DaysOfWeek)Enum.Parse(typeof(DaysOfWeek), dayName);
Console.WriteLine(day); // Εκτυπώνει “Tuesday”

Με το TryParse(), μπορείς να ελέγξεις αν η μετατροπή ήταν επιτυχής:

string dayName = “Friday”;
bool success = Enum.TryParse(dayName, out DaysOfWeek day);
if (success)
{
Console.WriteLine(day); // Εκτυπώνει “Friday”
}

4. Βελτίωση της αναγνωσιμότητας με Enum.GetNames() και Enum.GetValues()

Μπορείς να χρησιμοποιήσεις τις μεθόδους Enum.GetNames() και Enum.GetValues() για να πάρεις όλα τα ονόματα ή τις τιμές ενός enum:

foreach (string name in Enum.GetNames(typeof(DaysOfWeek)))
{
Console.WriteLine(name); // Εκτυπώνει όλα τα ονόματα: Monday, Tuesday, κ.λπ.
}

foreach (int value in Enum.GetValues(typeof(DaysOfWeek)))
{
Console.WriteLine(value); // Εκτυπώνει όλες τις τιμές: 0, 1, 2, κ.λπ.
}

5. Χρήση των enum ως Flags (προχωρημένο παράδειγμα)

Όταν χρησιμοποιείς το [Flags] attribute, μπορείς να αποθηκεύσεις και να χειριστείς πολλαπλά enum values ταυτόχρονα, σαν να ήταν μια συλλογή. Αυτό είναι πολύ χρήσιμο για συστήματα που χρειάζονται συνδυασμό καταστάσεων ή δικαιωμάτων (π.χ., διαχείριση αρχείων ή δικαιώματα χρήστη).

[Flags]
public enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write
}

FileAccess myAccess = FileAccess.Read | FileAccess.Write;
Console.WriteLine(myAccess); // Εκτυπώνει “Read, Write”

6. Προκαθορισμένες Τιμές και Χρήση ως Μάσκα

Μπορείς να χρησιμοποιήσεις τα enum σαν μάσκες, ώστε να τσεκάρεις συγκεκριμένες τιμές σε μια συνδυασμένη τιμή. Το [Flags] attribute κάνει αυτήν τη διαδικασία πιο φυσική, αλλά μπορείς να χρησιμοποιήσεις δυαδικές πράξεις ακόμα και χωρίς το attribute.

public enum Colors
{
Red = 1, // 001
Green = 2, // 010
Blue = 4 // 100
}

Colors myColor = Colors.Red | Colors.Green;
bool hasRed = (myColor & Colors.Red) == Colors.Red;
Console.WriteLine(hasRed); // Εκτυπώνει “True”

7. Αποθήκευση enum σε Βάσεις Δεδομένων

Τα enum συχνά αποθηκεύονται σε βάσεις δεδομένων ως ακέραιες τιμές, γιατί έτσι είναι ευκολότερο να αποθηκευτούν και να ανακτηθούν από το σύστημα. Όταν αποθηκεύεις ένα enum, αποθηκεύεις την αριθμητική του τιμή, ενώ όταν το ανακτάς, το μετατρέπεις ξανά στο αντίστοιχο enum value.

Παράδειγμα αποθήκευσης:

int status = (int)OrderStatus.Completed;

Και αντίστοιχα κατά την ανάκτηση:

OrderStatus status = (OrderStatus)storedStatus;

8. Ορισμός enum με διαφορετικούς τύπους δεδομένων

Από προεπιλογή, τα enum χρησιμοποιούν ακέραιες τιμές τύπου int, αλλά μπορείς να χρησιμοποιήσεις άλλους ακέραιους τύπους (π.χ. byte, long), αν χρειάζεται να περιορίσεις τη μνήμη ή να υποστηρίξεις μεγαλύτερες τιμές.

public enum ByteEnum : byte
{
One = 1,
Two = 2,
Three = 3
}

Συνοψίζοντας:

Τα enum είναι μια ευέλικτη δομή στην C# που σε βοηθά να αναπαριστάς σύνολα σταθερών με κατανοητά ονόματα, βελτιώνοντας την αναγνωσιμότητα και την ευκολία χρήσης του κώδικα. Πέρα από τη βασική χρήση τους, μπορούν να χρησιμοποιηθούν σε συνδυασμό με flags, να υποστηρίξουν μετατροπές σε και από strings και να χειριστούν πολλαπλές τιμές μέσω δυαδικών πράξεων. Είναι ιδανικά για περιπτώσεις όπου χρειάζεσαι καθορισμένα σύνολα σταθερών τιμών με φιλικά ονόματα.