VB.NET 列舉(Enum) 筆記(基礎篇)
Enum 用來表示一組固定選項。比起在程式中到處使用數字或字串,列舉可以用清楚的名稱代表狀態、類型、等級或選項,讓程式更容易閱讀,也比較不容易把不相關的值混在一起。
列舉適合用在「選項固定、名稱有意義、程式會反覆判斷」的情境。這篇以 Windows Forms 範例說明基本宣告、指定數值、Select Case、ComboBox、文字轉列舉與 <Flags> 組合列舉。
先理解 Enum 在解決什麼
Enum 是固定選項的命名集合
若某個欄位只會有固定幾種結果,例如座位狀態、取件時段、提醒方式、顯示模式,就很適合使用列舉。列舉的重點是讓程式看到名稱,而不是猜測數字或字串的意思。
- 可讀性:
SeatStatus.Reserved比2更容易理解。 - 集中管理:固定選項集中宣告,不散落在表單事件中。
- 型別限制:變數明確屬於某個列舉型別,不容易混入無關值。
- 適合判斷:搭配
Select Case可讓流程分支更清楚。
適合使用 Enum 的資料特徵:
- 選項固定:例如空位、已預約、使用中、暫停開放。
- 狀態有限:流程不會每天新增不同文字。
- 需要反覆判斷:多處程式都會根據狀態做不同處理。
| 做法 | 問題 | 適合程度 |
|---|---|---|
| 直接用數字 | 需要記住每個數字代表什麼。 | 只適合非常短且不公開的暫時計算。 |
| 直接用字串 | 容易拼錯,也不容易集中管理。 | 適合單純顯示,不適合流程判斷。 |
| 使用 Enum | 需要先定義型別,但結構較清楚。 | 適合固定選項與狀態判斷。 |
宣告 Enum 與指定數值
基本語法
Public Enum 列舉名稱
成員一
成員二
成員三
End Enum
未指定數值時,第一個成員預設為 0,後續依序遞增。若需要對應資料庫、外部代碼或固定規格,就應明確指定數值。
場景一:閱讀座位狀態
這個範例用閱讀座位狀態示範基本列舉。表單建立一個目前狀態,再依照列舉值顯示對應文字。
需要的主控項
ButtonShowSeat:顯示座位狀態。LabelSeatStatus:顯示結果。
範例程式碼
Public Enum SeatStatus
Available
Reserved
InUse
Closed
End Enum
Public Class Form1
Private Sub ButtonShowSeat_Click(sender As Object, e As EventArgs) Handles ButtonShowSeat.Click
Dim currentStatus As SeatStatus = SeatStatus.Reserved
LabelSeatStatus.Text = "座位狀態:" & currentStatus.ToString()
End Sub
End Class
邏輯解析
SeatStatus把座位可能狀態集中定義。currentStatus的型別明確是SeatStatus。ToString()會輸出列舉成員名稱。
場景二:櫃位燈號指定代碼
列舉可以明確指定數值。當列舉值需要對應外部代碼、硬體狀態或資料庫欄位時,指定數值會比依賴預設遞增更穩定。
需要的主控項
ButtonShowLight:顯示燈號代碼。LabelLight:顯示結果。
範例程式碼
Public Enum CounterLightCode
Off = 0
Green = 10
Yellow = 20
Red = 30
End Enum
Public Class Form1
Private Sub ButtonShowLight_Click(sender As Object, e As EventArgs) Handles ButtonShowLight.Click
Dim light As CounterLightCode = CounterLightCode.Yellow
LabelLight.Text = "燈號:" & light.ToString() & "|代碼:" & CInt(light).ToString()
End Sub
End Class
邏輯解析
CounterLightCode.Yellow對應整數值20。CInt(light)可把列舉值轉成整數。- 需要與外部代碼對應時,明確指定數值比較安全。
搭配 Select Case 進行判斷
場景三:取件時段提示文字
列舉很適合搭配 Select Case。每個 Case 都對應一個有名稱的列舉值,流程會比數字判斷清楚。
需要的主控項
ButtonShowPickup:顯示取件提示。LabelPickup:顯示結果。
範例程式碼
Public Enum PickupWindow
Morning
Noon
Evening
Weekend
End Enum
Public Class Form1
Private Sub ButtonShowPickup_Click(sender As Object, e As EventArgs) Handles ButtonShowPickup.Click
Dim window As PickupWindow = PickupWindow.Evening
LabelPickup.Text = BuildPickupText(window)
End Sub
Private Function BuildPickupText(ByVal window As PickupWindow) As String
Select Case window
Case PickupWindow.Morning
Return "取件時段:上午 09:00 - 11:30"
Case PickupWindow.Noon
Return "取件時段:中午 12:00 - 13:30"
Case PickupWindow.Evening
Return "取件時段:傍晚 17:30 - 20:00"
Case PickupWindow.Weekend
Return "取件時段:週末 10:00 - 16:00"
Case Else
Return "取件時段未設定"
End Select
End Function
End Class
邏輯解析
PickupWindow表示固定取件時段。Select Case讓每個狀態對應一段清楚處理。Case Else可作為保護分支,避免未處理狀態沒有回應。
ComboBox 與字串轉列舉
場景四:櫃台服務區下拉選單
列舉可直接放進 ComboBox 當資料來源。讀取時再把 SelectedItem 轉回列舉型別,後續判斷就不用處理散亂字串。
需要的主控項
ComboBoxZone:選擇服務區。ButtonReadZone:讀取選項。LabelZone:顯示結果。
範例程式碼
Public Enum ServiceZone
FrontDesk
ReadingRoom
CopyCorner
ReturnShelf
End Enum
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ComboBoxZone.DataSource = [Enum].GetValues(GetType(ServiceZone))
End Sub
Private Sub ButtonReadZone_Click(sender As Object, e As EventArgs) Handles ButtonReadZone.Click
Dim zone As ServiceZone = CType(ComboBoxZone.SelectedItem, ServiceZone)
LabelZone.Text = "目前服務區:" & BuildZoneText(zone)
End Sub
Private Function BuildZoneText(ByVal zone As ServiceZone) As String
Select Case zone
Case ServiceZone.FrontDesk
Return "櫃台報到區"
Case ServiceZone.ReadingRoom
Return "安靜閱讀區"
Case ServiceZone.CopyCorner
Return "影印協助區"
Case ServiceZone.ReturnShelf
Return "歸還書架區"
Case Else
Return "未設定"
End Select
End Function
End Class
邏輯解析
[Enum].GetValues可取得列舉的所有值。ComboBoxZone.SelectedItem可轉回ServiceZone。- 畫面顯示文字可透過方法轉成中文,不一定直接顯示列舉名稱。
場景五:輸入文字安全轉成列舉
當列舉值來自文字輸入、設定檔或外部資料時,不建議直接使用 Parse。使用 Enum.TryParse 可以避免格式錯誤時直接拋出例外。
需要的主控項
TextBoxWindow:輸入取件時段名稱,例如Morning。ButtonParseWindow:轉換文字。LabelParseResult:顯示轉換結果。
範例程式碼
Public Class Form1
Private Sub ButtonParseWindow_Click(sender As Object, e As EventArgs) Handles ButtonParseWindow.Click
Dim parsedWindow As PickupWindow
Dim inputText As String = TextBoxWindow.Text.Trim()
If [Enum].TryParse(Of PickupWindow)(inputText, True, parsedWindow) Then
LabelParseResult.Text = "轉換成功:" & parsedWindow.ToString()
Else
LabelParseResult.Text = "轉換失敗:找不到此取件時段"
End If
End Sub
End Class
邏輯解析
TryParse轉換成功會回傳True。- 第二個參數設為
True,代表不區分大小寫。 - 外部文字來源不穩定時,
TryParse比Parse更適合。
Flags 列舉:可組合的選項
<Flags> 列舉:適合表示可以同時存在的多個選項,例如通知管道、功能開關、權限組合。每個成員值通常使用 1、2、4、8 這類二的冪次方。
場景六:活動提醒管道
單選狀態不需要 <Flags>,但若同一筆設定可以同時選擇多個項目,就適合使用。這個範例用活動提醒管道示範組合與檢查。
需要的主控項
CheckBoxScreen:螢幕顯示。CheckBoxSms:簡訊提醒。CheckBoxEmail:Email 提醒。ButtonCheckChannel:檢查提醒管道。LabelChannel:顯示結果。
範例程式碼
<Flags>
Public Enum ReminderChannel
None = 0
Screen = 1
Sms = 2
Email = 4
End Enum
Public Class Form1
Private Sub ButtonCheckChannel_Click(sender As Object, e As EventArgs) Handles ButtonCheckChannel.Click
Dim channels As ReminderChannel = ReminderChannel.None
If CheckBoxScreen.Checked Then
channels = channels Or ReminderChannel.Screen
End If
If CheckBoxSms.Checked Then
channels = channels Or ReminderChannel.Sms
End If
If CheckBoxEmail.Checked Then
channels = channels Or ReminderChannel.Email
End If
If (channels And ReminderChannel.Sms) = ReminderChannel.Sms Then
LabelChannel.Text = "已包含簡訊提醒|目前設定:" & channels.ToString()
Else
LabelChannel.Text = "未包含簡訊提醒|目前設定:" & channels.ToString()
End If
End Sub
End Class
邏輯解析
Or用來把多個旗標組合在一起。And用來檢查目前組合是否包含指定旗標。None = 0代表沒有任何選項。- Flags 成員值使用 1、2、4,才能讓位元組合彼此不重疊。
使用限制:若某個欄位一次只能有一種狀態,例如「空位、已預約、使用中」三選一,就不需要使用 <Flags>。Flags 適合多選組合,不適合單選流程狀態。
實務判斷與常見誤區
常見問題整理
- 把會變動的資料做成 Enum:例如商品類別、部門清單、客戶類型若會由資料庫維護,就不適合硬寫成列舉。
- 只依賴預設數值:若列舉值要存到資料庫或對接外部系統,應明確指定數值。
- 把顯示文字直接等同列舉名稱:列舉名稱適合程式閱讀,畫面文字可另外轉換。
- Flags 值沒有使用 1、2、4、8:可能造成組合判斷錯誤。
- 濫用 Flags:單選狀態不需要 Flags。
| 需求 | 建議做法 | 原因 |
|---|---|---|
| 固定單選狀態 | 一般 Enum。 |
清楚、安全、適合流程判斷。 |
| 可同時選多項 | <Flags> Enum。 |
可用位元運算組合多個選項。 |
| 資料庫會維護選項 | 資料表或設定檔。 | 不需要每次新增選項都改程式。 |
| 畫面要顯示中文 | 建立轉換方法。 | 避免把顯示文字與程式名稱綁死。 |
重點整理
Enum適合表示固定且具意義的選項集合。- 未指定數值時,列舉成員預設從 0 開始遞增。
- 需要對應資料庫或外部代碼時,建議明確指定數值。
Select Case搭配列舉可讓流程判斷更清楚。[Enum].GetValues可取得列舉所有值,適合搭配ComboBox。- 外部文字轉列舉時,
TryParse比直接Parse更安全。 <Flags>適合可多選組合的情境,成員值應使用 1、2、4、8。- 若選項會頻繁變動或由資料庫維護,就不適合硬寫成列舉。