Enum是什麼?

在 C# 中,enum(列舉)是一種特殊的數據類型,用來定義一組命名的整數常數。它可以讓你將一組相關的常數組織在一起,並使用有意義的名稱來表示這些常數,而不是直接使用數字。這樣可以使代碼更具可讀性和可維護性。

enum 的基本概念

定義:你可以使用 enum 關鍵字來定義一個列舉類型。列舉類型中的每個成員都對應一個整數值。
用途:列舉主要用於表示固定的、有限的選項或狀態。例如,星期幾、顏色、訂單狀態等。


如何定義和使用 enum

  1. 定義列舉
    你可以定義一個列舉類型,例如:
public enum DaysOfWeek
{
    Sunday,    // 默認值是 0
    Monday,    // 默認值是 1
    Tuesday,   // 默認值是 2
    Wednesday, // 默認值是 3
    Thursday,  // 默認值是 4
    Friday,    // 默認值是 5
    Saturday   // 默認值是 6
}

這段代碼定義了一個名為 DaysOfWeek 的列舉,它包含了一周七天的名稱。每個成員都對應一個整數值,從 0 開始,依次遞增。

  1. 使用列舉
    你可以使用列舉來表示特定的值:
DaysOfWeek today = DaysOfWeek.Monday;

if (today == DaysOfWeek.Monday)
{
    Console.WriteLine("今天是星期一");
}
  1. 自定義整數值
    你也可以手動指定列舉成員的整數值:
public enum ErrorCode
{
    Success = 0,
    NotFound = 404,
    Unauthorized = 401,
    InternalError = 500
}
  1. 各種基本操作
using System;

class Program
{
    // 定義一個枚舉類型 State,其中包含幾個狀態值
    public enum Fruits
    {
        Apple,   // 默認為 0
        Mango,   // 默認為 1
        Banana,   // 默認為 2
        Tomato,  // 默認為 3
        Lemon = 9 // 顯式指定 Lemon 的值為 9
    }

    // Main 方法是程式的進入點
    public static void Main()
    {
        // 定義一個 Fruits 類型的變數 fruit,並初始化為 Apple 狀態
        Fruits fruit = Fruits.Apple;

        // 列出 Fruits 枚舉中的所有名稱
        foreach (string en in Enum.GetNames(typeof(Fruits)))
            Console.WriteLine("Enum Name: " + en);

        // 列舉 Fruits 枚舉中的所有值
        // 在這段程式碼中,fruit 是一個類型為 Fruits 的變數。
        // fruit.GetType() 方法返回這個變數的 "Type" 物件。
        // 由於 fruit 是 Fruits 枚舉的實例,因此 fruit.GetType() 返回的是 Fruits 類型的 Type 物件。
        foreach (int v in Enum.GetValues(fruit.GetType()))
            Console.WriteLine("Enum Value: " + v.ToString());

        // 將枚舉值轉換為字串
        Console.WriteLine("Enum To String: " + fruit.ToString());

        // 將字串轉換為枚舉值(true-忽略大小寫)
        fruit = (Fruits)Enum.Parse(typeof(Fruits), "Banana", true);
        Console.WriteLine("String To Enum: " + fruit);

        // 測試將一個無效的字串轉換為枚舉
        try
        {
            Console.WriteLine("String To Enum(not found): " +
                                    Enum.Parse(typeof(Fruits), "aaa"));
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error when Enum.Parse: " + ex.Message);
        }

        // 將枚舉值轉換為對應的整數
        Console.WriteLine("Enum to Int: " + fruit + " " + (int)fruit);

        // 將整數轉換回枚舉值
        fruit = (Fruits)9;
        Console.WriteLine("Int to Enum: " + fruit);

        // 將不存在於枚舉中的整數轉換為枚舉類型不會拋出錯誤!!
        fruit = (Fruits)100;
        Console.WriteLine("Int(100) to Enum: " + fruit);

        // 範例展示如何取得下一個和上一個枚舉值
        fruit = Fruits.Banana;
        Fruits next = (Fruits)((int)fruit + 1);
        Fruits prev = (Fruits)((int)fruit - 1);
        Console.WriteLine("Now = " + fruit + " Next = " + next + " Prev = " + prev);
    }
}

Output: 
        Enum Name: Apple
        Enum Name: Mango
        Enum Name: Banana
        Enum Name: Tomato
        Enum Name: Lemon
        Enum Value: 0
        Enum Value: 1
        Enum Value: 2
        Enum Value: 3
        Enum Value: 9
        Enum To String: Apple
        String To Enum: Banana
        Error when Enum.Parse: Requested value 'aaa' was not found.
        Enum to Int: Banana 2
        Int to Enum: Lemon
        Int(100) to Enum: 100
        Now = Banana Next = Tomato Prev = Mango

在這裡,Success 的值是 0,NotFound 的值是 404,以此類推。這樣你可以將列舉成員的值設置為更具意義的數字。

列舉的優點

  • 可讀性:使用列舉可以提高代碼的可讀性,因為它用有意義的名稱代替數字。
  • 安全性:列舉使代碼更加安全,因為你只能使用列舉中定義的值,這樣可以避免使用無效的數字。
  • 維護性:當你需要修改列舉的值時,只需在列舉定義中更改一次,代碼中的所有引用都會自動更新。

Enum.TryParse 的用法

Enum.TryParse(字串, out 列舉變量);

  • 字串:你想要轉換的字串,比如 "orderStatusString"。
  • 列舉變量:用來存儲轉換結果的變量,這個變量必須是對應列舉類型的。

實際例子

假設你在開發一個線上訂餐系統,你有一個列舉類型 OrderStatus 來表示訂單的狀態,定義如下:

public enum OrderStatus
{
    Pending,
    Preparing,
    Completed,
    Cancelled
}

你收到了一個來自前端的訂單狀態字串(例如從用戶界面發送過來的狀態信息),並需要將這個字串轉換為 OrderStatus 列舉,以便進行進一步處理。

假設你收到的狀態字串是 "Preparing",你可以使用 Enum.TryParse 將這個字串轉換為 OrderStatus 列舉,然後根據狀態做出相應的操作:

string orderStatusString = "Preparing";
OrderStatus status;

if (Enum.TryParse(orderStatusString, out status))
{
    // 如果轉換成功,status 現在是 OrderStatus.Preparing
    Console.WriteLine($"訂單狀態是: {status}");
    
    // 根據狀態執行不同的操作
    switch (status)
    {
        case OrderStatus.Pending:
            Console.WriteLine("訂單待處理。");
            break;
        case OrderStatus.Preparing:
            Console.WriteLine("訂單正在準備中。");
            break;
        case OrderStatus.Completed:
            Console.WriteLine("訂單已完成。");
            break;
        case OrderStatus.Cancelled:
            Console.WriteLine("訂單已取消。");
            break;
    }
}
else
{
    // 如果轉換失敗
    Console.WriteLine("無法解析訂單狀態。");
}

參考資料:
教學
為何好用?

解釋:

收到的字串:從前端發來的字串 "Preparing" 代表訂單正在準備中。
Enum.TryParse 的作用:將 "Preparing" 這個字串轉換為 OrderStatus.Preparing 列舉值。
轉換成功:你可以使用 status 變量來檢查訂單狀態並執行相應的操作,例如顯示正在準備中的信息。
轉換失敗:如果傳入的字串不符合任何一個列舉值,Enum.TryParse 會返回 false,你可以處理這種情況,比如顯示錯誤信息。
這樣,你就能用 Enum.TryParse 將字串轉換為列舉,從而方便地處理不同的訂單狀態。