2024年5月15日 星期三

2.VB.NET 基礎篇 筆記 - 陣列 (Array)

VB.NET 陣列 (Array) 筆記(基礎篇)

VB.NET 陣列 (Array) 筆記(基礎篇)

VB.NET 中處理多筆同型態資料時,如果每一筆內容都用獨立變數保存,後續的統計、輸出與維護會很快失去一致性。Array 陣列的主要用途,就是把相同型別的資料集中管理,並透過索引位置讀寫指定元素。

陣列的基礎可先抓住三件事:資料型別固定、位置由索引管理、宣告時的括號數字代表「最大索引」而不是「總筆數」。只要這三點清楚,後續的一維陣列、二維陣列、ReDim 與索引邊界判斷,都會比較容易理解。

陣列原理分析

運作邏輯說明

可把陣列視為一組連續編號的儲存格,每一格都保存相同資料型別的值。只要知道索引值,就能直接找到對應元素。

  • 集中管理:原本分散在多個變數中的內容,可以統一放入同一個資料結構。
  • 索引定位:第一個元素的索引為 0,之後依序增加 1。
  • 邊界明確:陣列可用位置有限,若讀取或寫入超出範圍的索引,會產生執行錯誤。

使用陣列前需先掌握的重點:

  1. 元素型別一致:一般強型別陣列只能放入指定型別,例如 Integer() 只能放整數,String() 只能放字串。
  2. 索引不等於筆數:若陣列長度為 5,最後一個索引是 4,不是 5。
  3. 宣告數字是最大索引:Dim values(2) 代表可用索引為 0、1、2,因此總共有 3 格。
  4. 適合固定結構資料:例如月份、成績、部門代號、固定欄位表格資料等。

宣告方式與基本操作

執行環境與物件配置說明

以下範例皆使用 Windows Forms。測試前請建立 Windows Forms 專案,並在 Form1 中依場景放入對應控制項。

  • Button1:執行範例邏輯。
  • Label1:顯示多行輸出結果,建議將 AutoSize 設為 False,並適度放大寬高。
  • TextBox1:本篇未作為必要控制項;若後續加入查詢或輸入範例,可再使用。

場景一:宣告一維陣列並依索引讀取資料

一維陣列適合處理單列資料,例如班級名稱、月份、部門代號與固定數量的設定值。此類情境的重點,在於先建立陣列,再依索引讀取指定元素。

範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim teamNames() As String = {"開發一組", "開發二組", "測試組", "維運組"}

        Dim firstTeam As String = teamNames(0)
        Dim thirdTeam As String = teamNames(2)

        Label1.Text = "第一個小組:" & firstTeam & vbCrLf &
                      "第三個小組:" & thirdTeam
    End Sub
End Class
畫面輸出結果(Label1.Text)
第一個小組:開發一組 第三個小組:測試組
邏輯解析
  • Dim teamNames() As String = {...} 代表建立字串型別的一維陣列,並直接放入四筆初始值。
  • teamNames(0) 取得第一筆資料,teamNames(2) 取得第三筆資料。
  • 陣列讀取的依據不是資料內容,而是索引位置。

場景二:搭配 For 迴圈批次填入資料

當陣列內容具有明顯規律,例如流水號、等差數列、月份編號或固定計算結果時,常見做法是透過 For 迴圈依索引批次填值。

範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim weeklyQuota(3) As Integer
        Dim result As String = "每週出貨目標:" & vbCrLf

        For i As Integer = 0 To weeklyQuota.Length - 1
            weeklyQuota(i) = (i + 1) * 120
        Next

        For i As Integer = 0 To weeklyQuota.Length - 1
            result &= "第 " & (i + 1).ToString() & " 週:" &
                      weeklyQuota(i).ToString() & " 件" & vbCrLf
        Next

        Label1.Text = result
    End Sub
End Class
畫面輸出結果(Label1.Text)
每週出貨目標: 第 1 週:120 件 第 2 週:240 件 第 3 週:360 件 第 4 週:480 件
邏輯解析
  • Dim weeklyQuota(3) As Integer 代表建立四格整數陣列,可用索引為 0 到 3。
  • Length 代表元素總數,因此本例的 weeklyQuota.Length 為 4。
  • Length - 1 代表最後一個有效索引,常用於控制一維陣列的迴圈邊界。
  • 此類寫法適合需要「知道位置」的批次處理。

場景三:使用 ReDim 與 ReDim Preserve 調整大小

若初始筆數尚未固定,可先宣告動態陣列,再依實際需求重新配置長度。此時常見的語法是 ReDimReDim Preserve

範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim taskNames() As String

        ReDim taskNames(1)
        taskNames(0) = "需求確認"
        taskNames(1) = "版面設計"

        ReDim Preserve taskNames(3)
        taskNames(2) = "功能開發"
        taskNames(3) = "驗收測試"

        Label1.Text = String.Join(" → ", taskNames)
    End Sub
End Class
畫面輸出結果(Label1.Text)
需求確認 → 版面設計 → 功能開發 → 驗收測試
邏輯解析
  • Dim taskNames() As String 只宣告名稱與型別,尚未配置實際長度。
  • ReDim taskNames(1) 建立兩格空間,可用索引為 0、1。
  • ReDim Preserve taskNames(3) 擴充為四格,並保留原有資料。
  • 若使用 ReDim 而未加 Preserve,原有資料會在重新配置後消失。

補充提醒:ReDim Preserve 不是單純「原地加格子」,而是重新配置陣列並保留資料。資料量很大或頻繁增減時,通常更適合使用 List(Of T)

場景四:使用二維陣列管理列欄資料

當資料同時具有列與欄的概念,例如月份 × 品項、員工 × 成績、部門 × 指標時,可使用二維陣列處理。二維陣列的第一個索引通常可視為列,第二個索引通常可視為欄。

範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim monthlyScore(2, 1) As Integer
        Dim result As String = "門市評分紀錄:" & vbCrLf

        monthlyScore(0, 0) = 86 : monthlyScore(0, 1) = 91
        monthlyScore(1, 0) = 79 : monthlyScore(1, 1) = 88
        monthlyScore(2, 0) = 93 : monthlyScore(2, 1) = 96

        For row As Integer = 0 To monthlyScore.GetUpperBound(0)
            result &= "門市 " & (row + 1).ToString() & ":"

            For col As Integer = 0 To monthlyScore.GetUpperBound(1)
                result &= monthlyScore(row, col).ToString() & " "
            Next

            result &= vbCrLf
        Next

        Label1.Text = result
    End Sub
End Class
畫面輸出結果(Label1.Text)
門市評分紀錄: 門市 1:86 91 門市 2:79 88 門市 3:93 96
邏輯解析
  • Dim monthlyScore(2, 1) As Integer 代表建立 3 列 × 2 欄的二維陣列。
  • GetUpperBound(0) 取得第一維的最後索引,GetUpperBound(1) 取得第二維的最後索引。
  • 二維陣列通常需搭配巢狀 For 迴圈,外層處理列,內層處理欄。

常用屬性與方法

陣列不只是儲存資料的容器,本身也提供一些常用成員,用來判斷長度、維度與資料位置。這些成員在寫迴圈、處理多維陣列與搜尋資料時都很常見。

名稱 用途說明
Length 取得陣列元素總數;一維陣列最常用來控制迴圈次數。
Rank 取得陣列維度數;一維回傳 1,二維回傳 2。
GetUpperBound(dimension) 取得指定維度的最後索引;適合多維陣列處理。
GetLowerBound(dimension) 取得指定維度的起始索引;一般 VB.NET 陣列起始索引為 0。
Array.IndexOf() 搜尋指定值在陣列中的位置;找不到時回傳 -1。

場景五:搜尋元素位置

若需確認某筆資料是否存在於陣列中,或想知道它位於哪一個索引位置,可使用 Array.IndexOf()

範例程式碼
VB.NET / Windows Forms
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim itemCodes() As String = {"M101", "M205", "M330", "M480"}
        Dim targetCode As String = "M330"

        Dim index As Integer = Array.IndexOf(itemCodes, targetCode)

        If index >= 0 Then
            Label1.Text = "品項代碼 " & targetCode & " 的索引位置為:" & index.ToString()
        Else
            Label1.Text = "查無指定代碼"
        End If
    End Sub
End Class
畫面輸出結果(Label1.Text)
品項代碼 M330 的索引位置為:2
邏輯解析
  • Array.IndexOf(itemCodes, targetCode) 會在陣列中搜尋指定值。
  • 若存在,回傳對應索引;若不存在,回傳 -1
  • 此方法適合查找代碼、部門名稱、身分別與固定分類資料。

使用限制與常見錯誤

陣列雖然單純、效率高,但邊界判斷必須嚴謹。初學者最常遇到的錯誤,就是把「長度」誤當成「最後索引」。

IndexOutOfRangeException

當程式試圖讀取或寫入不存在的索引位置時,系統會拋出 IndexOutOfRangeException。這代表目前要求使用的位置,已超出陣列可用範圍。

錯誤示意程式碼
VB.NET
Dim values(2) As Integer
values(0) = 15
values(1) = 30
values(2) = 45

' 以下寫法已超出可用索引範圍
values(3) = 60
邏輯解析
  • Dim values(2) As Integer 建立三格陣列,可用索引只有 0、1、2。
  • values(3) 已超出邊界,因此會直接產生執行例外。
  • 最常見的避免方式,是以 Length - 1GetUpperBound() 控制讀寫範圍。

使用陣列時需特別注意的限制:

  • 大小固定:標準陣列建立後長度固定;需要調整時,本質上是重新配置。
  • 型別固定:一般強型別陣列中的元素型別不可混用。
  • 邊界嚴格:任何超出索引範圍的存取都會導致例外。
  • ReDim Preserve 有成本:資料量大時需留意重新配置帶來的效能負擔。
  • 多維 Preserve 有限制:處理多維陣列時,ReDim Preserve 通常只能調整最後一個維度。

語法適用情境分析

比較項目 陣列 (Array) 泛型集合 (List)
結構特性 長度固定,位置明確,適合已知筆數資料。 筆數可動態增減,適合資料量經常改變的情況。
主要優勢 語法直接、索引清楚、存取效率高。 新增、刪除與擴充彈性較高。
主要限制 調整大小需重新配置,彈性較低。 使用前需理解集合方法,例如 AddRemoveCount
適用情境 資料筆數固定,且需要依索引快速定位。 資料量不固定,且需頻繁新增或移除資料。

重點整理

  1. VB.NET 陣列用來集中管理相同型別的多筆資料。
  2. 陣列索引從 0 開始;宣告中的數字是最大索引,不是總筆數。
  3. 一維陣列常搭配 Length - 1 控制迴圈,多維陣列常搭配 GetUpperBound()
  4. ReDim Preserve 可保留原資料並重新配置陣列,但頻繁調整時應考慮 List(Of T)
  5. 若需求重點是固定筆數與索引定位,陣列很適合;若需求重點是彈性增刪,通常使用 List(Of T) 更自然。