Visual Basic의 배열

배열은 서로 논리적으로 관련이 있는 요소라고 하는 값의 집합입니다. 예를 들어 배열은 학교 각 학년의 학생 수로 구성될 수 있으며, 배열의 각 요소는 단일 학년의 학생 수입니다. 마찬가지로 배열은 수업에 대한 학생의 성적으로 구성될 수 있으며, 배열의 각 요소는 단일 등급입니다.

개별 변수를 사용하여 각 데이터 항목을 저장할 수 있습니다. 예를 들어 애플리케이션에서 학생 성적을 분석하는 경우 각 학생의 성적(예: englishGrade1, englishGrade2 등)에 대해 별도의 변수를 사용할 수 있습니다. 이 접근 방식에는 세 가지 주요 제한 사항이 있습니다.

  • 디자인 타임에 정확히 얼마나 많은 성적을 처리해야 하는지 알고 있어야 합니다.
  • 많은 수의 성적을 빠르게 처리하는 것은 어려워집니다. 이렇게 하면 애플리케이션에 심각한 버그가 있을 가능성이 훨씬 높아집니다.
  • 유지 관리가 어렵습니다. 새 등급을 추가하면 애플리케이션을 수정, 다시 컴파일 및 다시 배포해야 합니다.

배열을 사용하면 관련성 있는 값을 동일한 이름으로 참조하고, 인덱스 또는 첨자라는 숫자를 사용하여 서로 구분할 수 있습니다. 배열의 인덱스 범위는 0부터 배열의 총 요소 수보다 작은 수까지입니다. Visual Basic 구문을 사용하여 배열의 크기를 정의하는 경우 배열의 총 요소 수가 아니라 가장 높은 인덱스를 지정합니다. 배열을 단위로 사용할 수 있으며, 해당 요소를 반복하는 기능을 사용하면 디자인 타임에 포함된 요소 수를 정확히 알 필요가 없습니다.

설명하기 전에 몇 가지 빠른 예제는 다음과 같습니다.

' Declare a single-dimension array of 5 numbers.
Dim numbers(4) As Integer

' Declare a single-dimension array and set its 4 values.
Dim numbers = New Integer() {1, 2, 4, 8}

' Change the size of an existing array to 16 elements and retain the current values.
ReDim Preserve numbers(15)

' Redefine the size of an existing array and reset the values.
ReDim numbers(15)

' Declare a 6 x 6 multidimensional array.
Dim matrix(5, 5) As Double

' Declare a 4 x 3 multidimensional array and set array element values.
Dim matrix = New Integer(,) {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}

' Declare a jagged array
Dim sales()() As Double = New Double(11)() {}

1차원 배열의 배열 요소

students라는 배열을 만들어 학교에서 각 성적에 해당하는 학생 수를 저장하겠습니다. 요소의 인덱스 범위는 0부터 6까지입니다. 이 배열은 사용하는 것이 7개의 변수를 선언하는 것보다 더 간단합니다.

다음 그림은 배열 students를 보여줍니다. 각 배열 요소에서

  • 요소의 인덱스는 학년을 나타냅니다(인덱스 0은 유치원을 나타냄).

  • 요소에 포함된 값은 해당 학년의 학생 수를 나타냅니다.

학생 수의 배열을 보여주는 다이어그램

다음 예제에는 배열을 만들고 사용하는 Visual Basic 코드가 포함되어 있습니다.


Module SimpleArray
   Public Sub Main()
      ' Declare an array with 7 elements.
      Dim students(6) As Integer

      ' Assign values to each element.
      students(0) = 23
      students(1) = 19
      students(2) = 21
      students(3) = 17
      students(4) = 19
      students(5) = 20
      students(6) = 22
      
      ' Display the value of each element.
      For ctr As Integer = 0 To 6
         Dim grade As String = If(ctr = 0, "kindergarten", $"grade {ctr}")
         Console.WriteLine($"Students in {grade}: {students(ctr)}")
      Next
   End Sub
End Module
' The example displays the following output:
'     Students in kindergarten: 23
'     Students in grade 1: 19
'     Students in grade 2: 21
'     Students in grade 3: 17
'     Students in grade 4: 19
'     Students in grade 5: 20
'     Students in grade 6: 22

이 예제에서는 다음 세 가지를 수행합니다.

  • 7개의 요소가 있는 students 배열을 선언합니다. 배열 선언의 6 숫자는 배열의 마지막 인덱스(배열의 요소 수보다 1 작음)를 나타냅니다.
  • 배열의 각 요소에 값을 할당합니다. 배열 요소는 배열 이름을 사용하고 개별 요소의 인덱스를 괄호 안에 포함하여 액세스합니다.
  • 배열의 각 값을 나열합니다. 이 예제에서는 For 문을 사용하여 인덱스 숫자로 배열의 각 요소에 액세스합니다.

앞의 예제에서 students 배열은 하나의 인덱스가 사용되므로 1차원 배열입니다. 둘 이상의 인덱스 또는 아래 첨자를 사용하는 배열을 다차원 배열이라고 합니다. 자세한 내용은 이 문서의 나머지 부분과 Array Dimensions in Visual Basic을 참조하세요.

배열 만들기

여러 가지 방법으로 배열의 크기를 정의할 수 있습니다.

  • 배열이 정의될 때 크기를 지정할 수 있습니다.

    ' Declare an array with 10 elements.
    Dim cargoWeights(9) As Double               
    ' Declare a 24 x 2 array.
    Dim hourlyTemperatures(23, 1) As Integer
    ' Declare a jagged array with 31 elements.
    Dim januaryInquiries(30)() As String
    
  • 배열을 만들 때 New 절을 사용하여 배열의 크기를 제공할 수 있습니다.

    ' Declare an array with 10 elements.
    Dim cargoWeights() As Double = New Double(9) {}
    ' Declare a 24 x 2 array.
    Dim hourlyTemperatures(,) As Integer = New Integer(23, 1) {}
    ' Declare a jagged array with 31 elements. 
    Dim januaryInquiries()() As String = New String(30)() {}
    

기존 배열이 있는 경우 ReDim 문을 사용하여 해당 크기를 다시 정의할 수 있습니다. ReDim 문이 배열에 있는 값을 유지하도록 지정하거나 빈 배열을 만들도록 지정할 수 있습니다. 다음 예제에서는 ReDim 문을 사용하여 기존 배열의 크기를 수정하는 여러 가지 방법을 보여 줍니다.

' Assign a new array size and retain the current values.
ReDim Preserve cargoWeights(20)
' Assign a new array size and retain only the first five values.
ReDim Preserve cargoWeights(4)
' Assign a new array size and discard all current element values.
ReDim cargoWeights(15)

자세한 내용은 ReDim 문을 참조하세요.

배열에 값 저장

Integer형식의 인덱스를 사용하여 배열의 각 위치에 액세스할 수 있습니다. 괄호로 묶인 해당 인덱스를 통해 각 배열 위치를 참조하여 배열에 값을 저장하고 검색할 수 있습니다. 다차원 배열에 대한 인덱스는 쉼표(,)로 구분됩니다. 각 배열 차원에 대해 하나의 인덱스가 필요합니다.

다음 예제는 배열에 값을 저장하고 검색하는 몇 가지 문을 보여줍니다.


Module Example
   Public Sub Main()
      ' Create a 10-element integer array.
      Dim numbers(9) As Integer
      Dim value As Integer = 2
        
      ' Write values to it.
      For ctr As Integer = 0 To 9
         numbers(ctr) = value
         value *= 2
      Next
        
      ' Read and sum the array values.  
      Dim sum As Integer
      For ctr As Integer = 0 To 9
         sum += numbers(ctr)
      Next
      Console.WriteLine($"The sum of the values is {sum:N0}")
    End Sub
End Module
' The example displays the following output:
'     The sum of the values is 2,046

배열 리터럴로 배열 채우기

배열 리터럴을 사용하면 배열을 만드는 동시에 초기 값 집합으로 배열을 채울 수 있습니다. 배열 리터럴은 중괄호({})로 묶인 쉼표로 구분된 값 목록으로 구성됩니다.

배열 리터럴을 사용하여 배열을 만드는 경우 배열 형식을 제공하거나 형식 유추를 사용하여 배열 형식을 결정할 수 있습니다. 다음 예제에서는 두 가지 옵션을 모두 보여줍니다.

' Array literals with explicit type definition.
Dim numbers = New Integer() {1, 2, 4, 8}
' Array literals with type inference.
Dim doubles = {1.5, 2, 9.9, 18}
' Array literals with explicit type definition.
Dim articles() As String = { "the", "a", "an" }

' Array literals with explicit widening type definition.
Dim values() As Double = { 1, 2, 3, 4, 5 }

형식 유추를 사용하는 경우 리터럴 값 목록의 기준 형식에 의해 배열 형식이 결정됩니다. 기준 형식은 배열의 다른 모든 형식이 확장될 수 있는 형식입니다. 이 고유 형식을 확인할 수 없는 경우 기준 형식은 배열의 다른 모든 형식이 축소될 수 있는 고유 형식입니다. 이러한 고유 형식을 모두 확인할 수 없는 경우 기준 형식은 Object입니다. 예를 들어 배열 리터럴에 제공된 값 목록이 Integer, LongDouble형식의 값을 포함하는 경우 결과 배열은 Double형식입니다. IntegerLongDouble에만 확장되므로 Double이 기본 형식입니다. 자세한 내용은 Widening and Narrowing Conversions을 참조하세요.

참고

형식 멤버에서 지역 변수로 정의된 배열에 대해서만 형식 유추를 사용할 수 있습니다. 명시적 형식 정의가 없는 경우 클래스 수준에서 배열 리터럴로 정의된 배열은 Object[] 형식입니다. 자세한 내용은 지역 형식 유추를 참조하세요.

이전 예제에서는 모든 배열 리터럴이 Integer 형식인 경우에도 values를 형식 Double의 배열로 정의합니다. 배열 리터럴의 값이 Double 값으로 확장될 수 있으므로 이 배열을 만들 수 있습니다.

중첩된 배열 리터럴을 사용하여 다차원 배열을 만들고 채울 수 있습니다. 중첩된 배열 리터럴에는 결과 배열과 일치하는 차원 수가 있어야 합니다. 다음 예제는 중첩된 배열 리터럴을 사용하여 정수의 2차원 배열을 만듭니다.

' Create and populate a 2 x 2 array.
Dim grid1 = {{1, 2}, {3, 4}}
' Create and populate a 2 x 2 array with 3 elements.
Dim grid2(,) = {{1, 2}, {3, 4}, {5, 6}}

중첩된 배열 리터럴을 사용하여 배열을 만들고 채우는 경우 중첩된 배열 리터럴의 요소 수가 일치하지 않으면 오류가 발생합니다. 배열 리터럴과 다른 수의 차원을 가지도록 배열 변수를 명시적으로 선언하는 경우에도 오류가 발생합니다.

1차원 배열에 대해 할 수 있는 것처럼 중첩된 배열 리터럴을 사용하여 다차원 배열을 만들 때 형식 유추를 사용할 수 있습니다. 유추된 형식은 모든 중첩 수준의 모든 배열 리터럴에 있는 모든 값에 대한 기준 형식입니다. 다음 예제는 IntegerDouble 형식의 값에서 Double[,] 형식의 2차원 배열을 만듭니다.

Dim arr = {{1, 2.0}, {3, 4}, {5, 6}, {7, 8}}

추가 예제를 보려면 방법: Visual Basic에서 배열 변수 초기화를 참조하세요.

배열 반복

배열을 반복하는 경우 가장 낮은 인덱스부터 가장 높은 인덱스까지, 또는 가장 높은 인덱스부터 가장 낮은 인덱스까지 배열의 각 요소에 액세스합니다. 대체로 For...Next 문 또는 For Each...Next 문을 사용하여 배열의 요소를 반복합니다. 배열의 상한을 모르는 경우 Array.GetUpperBound 메서드를 호출하여 인덱스의 가장 높은 값을 가져올 수 있습니다. 가장 낮은 인덱스 값은 거의 항상 0이지만 Array.GetLowerBound 메서드를 호출하여 인덱스의 가장 낮은 값을 가져올 수 있습니다.

다음 예제에서는 For...Next 문을 사용하여 1차원 배열을 반복합니다.


Module IterateArray
   Public Sub Main()
      Dim numbers = {10, 20, 30}

      For index = 0 To numbers.GetUpperBound(0)
         Console.WriteLine(numbers(index))
      Next
   End Sub
End Module
' The example displays the following output:
'  10
'  20
'  30

다음 예제에서는 For...Next 문을 사용하여 다차원 배열을 반복합니다. GetUpperBound 메서드에는 차원을 지정하는 매개 변수가 있습니다. GetUpperBound(0)는 첫 번째 차원의 가장 높은 인덱스를 반환하고, GetUpperBound(1)는 두 번째 차원의 가장 높은 인덱스를 반환합니다.


Module IterateArray
   Public Sub Main()
      Dim numbers = {{1, 2}, {3, 4}, {5, 6}}

      For index0 = 0 To numbers.GetUpperBound(0)
         For index1 = 0 To numbers.GetUpperBound(1)
            Console.Write($"{numbers(index0, index1)} ")
         Next
         Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output:
' Output 
'  1 2 
'  3 4 
'  5 6

다음 예제에서는 For Each...Next 문을 사용하여 1차원 배열과 2차원 배열을 반복합니다.


Module IterateWithForEach
   Public Sub Main()
      ' Declare and iterate through a one-dimensional array.
      Dim numbers1 = {10, 20, 30}
      
      For Each number In numbers1
         Console.WriteLine(number)
      Next
      Console.WriteLine()
      
      Dim numbers = {{1, 2}, {3, 4}, {5, 6}}

      For Each number In numbers
         Console.WriteLine(number)
      Next
   End Sub
End Module
' The example displays the following output:
'  10
'  20
'  30
'
'  1
'  2
'  3
'  4
'  5
'  6

배열 크기

배열 크기는 모든 차원의 길이 곱입니다. 현재 배열에 포함된 요소의 총 수를 나타냅니다. 예를 들어 다음 예제에서는 각 차원에 4개의 요소가 있는 2차원 배열을 선언합니다. 예제의 출력에서 보여주는 것과 같이 배열의 크기는 16(또는 (3 + 1) * (3 + 1))입니다.


Module Example
   Public Sub Main()
      Dim arr(3, 3) As Integer
      Console.WriteLine(arr.Length)     
   End Sub
End Module
' The example displays the following output:
'     16

참고

배열 크기에 대한 설명은 가변 배열에 적용되지 않습니다. 가변 배열 및 가변 배열의 크기를 결정하는 방법에 대한 자세한 내용은 가변 배열 섹션을 참조하세요.

Array.Length 속성을 사용하여 배열의 크기를 찾을 수 있습니다. Array.GetLength 메서드를 사용하여 다차원 배열의 각 차원 길이를 찾을 수 있습니다.

새 배열 개체를 할당하거나 ReDim을 사용하여 배열 변수의 크기를 조정할 수 있습니다. 다음 예제에서는 ReDim 문을 사용하여 100개 요소의 배열을 51개 요소의 배열로 변경합니다.


Module Example
   Public Sub Main()
      Dim arr(99) As Integer
      Console.WriteLine(arr.Length)
      
      Redim arr(50)
      Console.WriteLine(arr.Length)
   End Sub
End Module
' The example displays the following output:
'     100
'     51

 

배열의 크기를 처리할 때 유의해야 하는 여러 가지 사항이 있습니다.

메모
차원 길이 각 차원의 인덱스는 0부터 시작하므로 0부터 상한까지의 범위입니다. 따라서 지정된 차원의 길이는 해당 차원에 대해 선언된 상한보다 1만큼 더 큽니다.
길이 제한 배열의 각 차원 길이는 Integer 데이터 형식의 최대값, 즉 Int32.MaxValue 또는 (2 ^ 31) - 1로 제한됩니다. 그러나 배열의 총 크기는 시스템에서 사용 가능한 메모리에 의해서도 제한됩니다. 사용 가능한 메모리를 초과하는 배열을 초기화하려고 하면 런타임에서 OutOfMemoryException 예외가 throw됩니다.
크기 및 요소 크기 배열의 크기는 해당 요소의 데이터 형식과 독립적입니다. 크기는 항상 메모리에서 사용하는 바이트 수가 아니라 요소의 총 수를 나타냅니다.
메모리 소비 배열이 메모리에 저장되는 방법에 대해서는 어떠한 가정도 하지 않는 것이 좋습니다. 스토리지는 각 데이터 너비의 플랫폼마다 달라지므로 동일한 배열이 32비트 시스템보다 64비트 시스템에서 더 많은 메모리를 사용할 수 있습니다. 시스템 구성에 따라 배열을 초기화할 때 CLR(공용 언어 런타임)에서 스토리지를 할당하여 요소를 최대한 가깝게 압축하거나 모두 일반적인 하드웨어 경계에 맞출 수 있습니다. 또한 배열의 제어 정보로 인해 스토리지 오버헤드가 필요하며, 차원이 추가될 때마다 이 오버헤드가 증가합니다.

배열 형식

각 배열에는 데이터 형식이 있으며, 해당 요소의 데이터 형식과 다릅니다. 모든 배열에 대한 단일 데이터 형식은 없습니다. 대신, 배열의 데이터 형식은 배열의 차원 수 또는 차수와 배열에 있는 요소의 데이터 형식에 의해 결정됩니다. 두 배열 변수는 동일한 차수이고 해당 요소가 동일한 데이터 형식인 경우에만 동일한 데이터 형식입니다. 배열의 차원 길이는 배열 데이터 형식에 영향을 주지 않습니다.

모든 배열은 System.Array 클래스에서 상속되며 Array 형식으로 변수를 선언할 수 있지만, Array 형식의 배열을 만들 수는 없습니다. 예를 들어 다음 코드는 arr 변수를 Array 형식으로 선언하고 Array.CreateInstance 메서드를 호출하여 배열을 인스턴스화하며, 배열의 형식은 Object[]로 입증됩니다.


Module Example
   Public Sub Main()
      Dim arr As Array = Array.CreateInstance(GetType(Object), 19)
      Console.WriteLine(arr.Length)
      Console.WriteLine(arr.GetType().Name)
   End Sub
End Module
' The example displays the following output:
'     19
'     Object[]

또한 ReDim 문Array 형식으로 선언된 변수에 대해 작업할 수 없습니다. 이러한 이유 및 형식 안전성을 위해 모든 배열을 특정 형식으로 선언하는 것이 좋습니다.

배열이나 해당 요소의 데이터 형식을 여러 가지 방법으로 확인할 수 있습니다.

  • 변수에서 GetType 메서드를 호출하여 변수의 런타임 형식을 나타내는 Type 개체를 가져올 수 있습니다. Type 개체는 해당 속성과 메서드에 광범위한 정보를 보유합니다.
  • TypeName 함수에 변수를 전달하여 런타임 형식의 이름을 포함하는 String를 가져올 수 있습니다.

다음 예제에서는 GetType 메서드와 TypeName 함수를 모두 호출하여 배열의 형식을 확인합니다. 배열 형식은 Byte(,)입니다. Type.BaseType 속성은 또한 바이트 배열의 기본 형식이 Array 클래스임을 나타냅니다.


Module Example
   Public Sub Main()
      Dim bytes(9,9) As Byte
      Console.WriteLine($"Type of {nameof(bytes)} array: {bytes.GetType().Name}")
      Console.WriteLine($"Base class of {nameof(bytes)}: {bytes.GetType().BaseType.Name}")
      Console.WriteLine()
      Console.WriteLine($"Type of {nameof(bytes)} array: {TypeName(bytes)}")
   End Sub
End Module
' The example displays the following output:
' Type of bytes array: Byte[,]
' Base class of bytes: Array
' 
' Type of bytes array: Byte(,)


반환 값 및 매개 변수로 사용되는 배열

Function 프로시저에서 배열을 반환하려면 배열 데이터 형식 및 차원 수를 Function 문의 반환 형식으로 지정합니다. 함수 내에서 동일한 데이터 형식 및 차원 수의 지역 배열 변수를 선언합니다. Return 문에 지역 배열 변수를 괄호 없이 포함합니다.

Sub 또는 Function 프로시저에 대한 매개 변수로 배열을 지정하려면 지정된 데이터 형식 및 차원 수의 배열로 매개 변수를 정의합니다. 프로시저 호출에서 동일한 데이터 형식 및 차원 수의 배열 변수를 전달합니다.

다음 예제에서 GetNumbers 함수는 Integer 형식의 1차원 배열인 Integer()를 반환합니다. ShowNumbers 프로시저는 Integer() 인수를 사용합니다.


Module ReturnValuesAndParams
   Public Sub Main()
      Dim numbers As Integer() = GetNumbers()
      ShowNumbers(numbers)
   End Sub

   Private Function GetNumbers() As Integer()
      Dim numbers As Integer() = {10, 20, 30}
      Return numbers
   End Function

   Private Sub ShowNumbers(numbers As Integer())
      For index = 0 To numbers.GetUpperBound(0)
         Console.WriteLine($"{numbers(index)} ")
      Next
   End Sub
End Module
' The example displays the following output:
'   10
'   20
'   30
    

다음 예제에서 GetNumbersMultiDim 함수는 Integer 형식의 2차원 배열인 Integer(,)를 반환합니다. ShowNumbersMultiDim 프로시저는 Integer(,) 인수를 사용합니다.


Module Example
   Public Sub Main()
      Dim numbers As Integer(,) = GetNumbersMultidim()
      ShowNumbersMultidim(numbers)
   End Sub

   Private Function GetNumbersMultidim() As Integer(,)
      Dim numbers As Integer(,) = {{1, 2}, {3, 4}, {5, 6}}
      Return numbers
   End Function

   Private Sub ShowNumbersMultidim(numbers As Integer(,))
      For index0 = 0 To numbers.GetUpperBound(0)
         For index1 = 0 To numbers.GetUpperBound(1)
            Console.Write($"{numbers(index0, index1)} ")
         Next
         Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output:
'     1 2
'     3 4
'     5 6

가변 배열

애플리케이션의 데이터 구조가 2차원 배열이지만 사각형이 아닌 경우도 있습니다. 예를 들어 배열을 사용하여 매월 매일의 최고 기온에 대한 데이터를 저장할 수 있습니다. 배열의 첫 번째 차원은 월을 나타내지만 두 번째 차원은 일 수를 나타내며, 각 월의 일 수는 균일하지 않습니다. 배열의 배열이라고도 하는 가변 배열은 이러한 시나리오를 위해 디자인되었습니다. 가변 배열은 요소가 배열인 배열입니다. 가변 배열 및 가변 배열의 각 요소에는 하나 이상의 차원이 있을 수 있습니다.

다음 예제에는 각 요소가 일 배열인 월 배열을 사용합니다. 이 예제에서는 각 월에 일 수가 다르므로 가변 배열을 사용합니다. 이 예제에서는 가변 배열을 만들고, 값을 할당하고, 해당 값을 검색 및 표시하는 방법을 보여줍니다.

Imports System.Globalization

Module JaggedArray
   Public Sub Main()
      ' Declare the jagged array of 12 elements. Each element is an array of Double.
      Dim sales(11)() As Double
      ' Set each element of the sales array to a Double array of the appropriate size.
      For month As Integer = 0 To 11
         ' The number of days in the month determines the appropriate size.
         Dim daysInMonth As Integer =
            DateTime.DaysInMonth(Year(Now), month + 1)
         sales(month) = New Double(daysInMonth - 1) {}
      Next 

      ' Store values in each element.
      For month As Integer = 0 To 11
         For dayOfMonth = 0 To sales(month).GetUpperBound(0)
            sales(month)(dayOfMonth) = (month * 100) + dayOfMonth
         Next
      Next

      ' Retrieve and display the array values.
      Dim monthNames = DateTimeFormatInfo.CurrentInfo.AbbreviatedMonthNames
      ' Display the month names.
      Console.Write("    ")
      For ctr = 0 To sales.GetUpperBound(0)
         Console.Write($" {monthNames(ctr)}   ")
      Next   
      Console.WriteLine()
      ' Display data for each day in each month.
      For dayInMonth = 0 To 30
         Console.Write($"{dayInMonth + 1,2}.  ")
         For monthNumber = 0 To sales.GetUpperBound(0)
            If dayInMonth > sales(monthNumber).GetUpperBound(0) Then 
               Console.Write("       ")
            Else
               Console.Write($"{sales(monthNumber)(dayInMonth),-5}  ")
            End If
         Next   
         Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output:
'      Jan    Feb    Mar    Apr    May    Jun    Jul    Aug    Sep    Oct    Nov    Dec
'  1.  0      100    200    300    400    500    600    700    800    900    1000   1100
'  2.  1      101    201    301    401    501    601    701    801    901    1001   1101
'  3.  2      102    202    302    402    502    602    702    802    902    1002   1102
'  4.  3      103    203    303    403    503    603    703    803    903    1003   1103
'  5.  4      104    204    304    404    504    604    704    804    904    1004   1104
'  6.  5      105    205    305    405    505    605    705    805    905    1005   1105
'  7.  6      106    206    306    406    506    606    706    806    906    1006   1106
'  8.  7      107    207    307    407    507    607    707    807    907    1007   1107
'  9.  8      108    208    308    408    508    608    708    808    908    1008   1108
' 10.  9      109    209    309    409    509    609    709    809    909    1009   1109
' 11.  10     110    210    310    410    510    610    710    810    910    1010   1110
' 12.  11     111    211    311    411    511    611    711    811    911    1011   1111
' 13.  12     112    212    312    412    512    612    712    812    912    1012   1112
' 14.  13     113    213    313    413    513    613    713    813    913    1013   1113
' 15.  14     114    214    314    414    514    614    714    814    914    1014   1114
' 16.  15     115    215    315    415    515    615    715    815    915    1015   1115
' 17.  16     116    216    316    416    516    616    716    816    916    1016   1116
' 18.  17     117    217    317    417    517    617    717    817    917    1017   1117
' 19.  18     118    218    318    418    518    618    718    818    918    1018   1118
' 20.  19     119    219    319    419    519    619    719    819    919    1019   1119
' 21.  20     120    220    320    420    520    620    720    820    920    1020   1120
' 22.  21     121    221    321    421    521    621    721    821    921    1021   1121
' 23.  22     122    222    322    422    522    622    722    822    922    1022   1122
' 24.  23     123    223    323    423    523    623    723    823    923    1023   1123
' 25.  24     124    224    324    424    524    624    724    824    924    1024   1124
' 26.  25     125    225    325    425    525    625    725    825    925    1025   1125
' 27.  26     126    226    326    426    526    626    726    826    926    1026   1126
' 28.  27     127    227    327    427    527    627    727    827    927    1027   1127
' 29.  28            228    328    428    528    628    728    828    928    1028   1128
' 30.  29            229    329    429    529    629    729    829    929    1029   1129
' 31.  30            230           430           630    730           930           1130

이전 예제에서는 For...Next 루프를 사용하여 요소별로 가변 배열에 값을 할당합니다. 중첩된 배열 리터럴을 사용하여 가변 배열의 요소에 값을 할당할 수도 있습니다. 하지만 중첩된 배열 리터럴(예: Dim valuesjagged = {{1, 2}, {2, 3, 4}})을 사용하려고 시도하면 컴파일러 오류 BC30568이 발생합니다. 오류를 수정하려면 내부 배열 리터럴을 괄호로 묶습니다. 다음 예제와 같이 괄호는 배열 리터럴 식이 계산되도록 강제하며, 결과 값이 외부 배열 리터럴과 함께 사용됩니다.


Module Example
   Public Sub Main()
      Dim values1d = { 1, 2, 3 }
      Dim values2d = {{1, 2}, {2, 3}, {3, 4}}
      Dim valuesjagged = {({1, 2}), ({2, 3, 4})}
   End Sub
End Module

가변 배열은 요소에 배열이 포함된 1차원 배열입니다. 따라서 Array.Length 속성과 Array.GetLength(0) 메서드는 1차원 배열의 요소 수를 반환하고, Array.GetLength(1)는 가변 배열이 다차원 배열이 아니므로 IndexOutOfRangeException을 throw합니다. 각 하위 배열의 Array.Length 속성 값을 검색하여 각 하위 배열의 요소 수를 결정합니다. 다음 예제에서는 가변 배열의 요소 수를 결정하는 방법을 보여줍니다.


Module Example
   Public Sub Main()
      Dim jagged = { ({1, 2}), ({2, 3, 4}), ({5, 6}), ({7, 8, 9, 10}) }
      Console.WriteLine($"The value of jagged.Length: {jagged.Length}.")
      Dim total = jagged.Length
      For ctr As Integer = 0 To jagged.GetUpperBound(0)
         Console.WriteLine($"Element {ctr + 1} has {jagged(ctr).Length} elements.") 
         total += jagged(ctr).Length 
      Next
      Console.WriteLine($"The total number of elements in the jagged array: {total}")
   End Sub
End Module
' The example displays the following output:
'     The value of jagged.Length: 4.
'     Element 1 has 2 elements.
'     Element 2 has 3 elements.
'     Element 3 has 2 elements.
'     Element 4 has 4 elements.
'     The total number of elements in the jagged array: 15

길이가 0인 배열

Visual Basic은 초기화되지 않은 배열(값이 Nothing인 배열)과 길이가 0인 배열 또는 빈 배열(요소가 없는 배열)을 구분합니다. 초기화되지 않은 배열은 차원화되지 않았거나 할당된 값이 있는 배열입니다. 예를 들면 다음과 같습니다.

Dim arr() As String

길이가 0인 배열은 -1의 차원으로 선언됩니다. 예를 들면 다음과 같습니다.

Dim arrZ(-1) As String

다음과 같은 경우 길이가 0인 배열을 만들어야 할 수도 있습니다.

  • NullReferenceException 예외가 발생할 위험 없이 코드에서 Length 또는 Rank와 같은 Array 클래스의 멤버에 액세스하거나 UBound와 같은 Visual Basic 함수를 호출해야 하는 경우.

  • Nothing을 특별한 경우로 확인할 필요가 없도록 하여 코드를 보다 간단하게 유지하려는 경우.

  • 코드가 하나 이상의 프로시저에 길이가 0인 배열을 전달해야 하거나 하나 이상의 프로시저에서 길이가 0인 배열을 반환하는 API(애플리케이션 프로그래밍 인터페이스)와 상호 작용하는 경우

배열 분할

경우에 따라 단일 배열을 여러 배열로 분할해야 할 수 있습니다. 여기에는 배열을 분할할 지점을 식별한 다음 배열을 두 개 이상의 개별 배열에 삽입하는 작업이 포함됩니다.

참고

이 섹션에서는 일부 구분 기호를 기반으로 단일 문자열을 문자열 배열로 분할하는 것에 대해서는 설명하지 않습니다. 문자열 분할에 대한 자세한 내용은 String.Split 메서드를 참조하세요.

배열 분할에 대한 가장 일반적인 기준은 다음과 같습니다.

  • 배열의 요소 수입니다. 예를 들어 지정된 개수 이상의 요소 배열을 거의 같은 수의 부분으로 분할할 수 있습니다. 이를 위해 Array.Length 또는 Array.GetLength 메서드에 의해 반환된 값을 사용할 수 있습니다.

  • 배열을 분할해야 하는 위치를 나타내는 구분 기호 역할을 하는 요소의 값입니다. Array.FindIndexArray.FindLastIndex 메서드를 호출하여 특정 값을 검색할 수 있습니다.

배열을 분할해야 하는 인덱스를 결정한 후에는 Array.Copy 메서드를 호출하여 개별 배열을 만들 수 있습니다.

다음 예제에서는 배열을 거의 같은 크기의 두 배열로 분할합니다. (배열 요소의 총 수가 홀수이면 첫 번째 배열에는 두 번째 배열보다 요소가 하나 더 있습니다.)


Module Example
   Public Sub Main()
      ' Create an array of 100 elements.
      Dim arr(99) As Integer
      ' Populate the array.
      Dim rnd As new Random()
      For ctr = 0 To arr.GetUpperBound(0)
         arr(ctr) = rnd.Next()
      Next
      
      ' Determine how many elements should be in each array.
      Dim divisor = 2
      Dim remainder As Integer
      Dim boundary = Math.DivRem(arr.GetLength(0), divisor, remainder)
            
      ' Copy the array.
      Dim arr1(boundary - 1 + remainder), arr2(boundary - 1) as Integer
      Array.Copy(arr, 0, arr1, 0, boundary + remainder)
      Array.Copy(arr, boundary + remainder, arr2, 0, arr.Length - boundary) 
   End Sub
End Module

다음 예제에서는 값이 배열 구분 기호 역할을 하는 “zzz”인 요소의 존재에 따라 문자열 배열을 두 개의 배열로 분할합니다. 새 배열에는 구분 기호가 포함된 요소가 포함되지 않습니다.


Module Example
   Public Sub Main()
      Dim rnd As New Random()
      
      ' Create an array of 100 elements.
      Dim arr(99) As String
      ' Populate each element with an arbitrary ASCII character.
      For ctr = 0 To arr.GetUpperBound(0)
         arr(ctr) = ChrW(Rnd.Next(&h21, &h7F))
      Next
      ' Get a random number that will represent the point to insert the delimiter.
      arr(rnd.Next(0, arr.GetUpperBound(0))) = "zzz"

      ' Find the delimiter.
      Dim location = Array.FindIndex(arr, Function(x) x = "zzz")

      ' Create the arrays.
      Dim arr1(location - 1) As String
      Dim arr2(arr.GetUpperBound(0) - location - 1) As String
      
      ' Populate the two arrays.
      Array.Copy(arr, 0, arr1, 0, location)
      Array.Copy(arr, location + 1, arr2, 0, arr.GetUpperBound(0) - location)
   End Sub
End Module

배열 조인

여러 배열을 더 큰 단일 배열로 결합할 수도 있습니다. 이를 위해 Array.Copy 메서드를 사용할 수도 있습니다.

참고

이 섹션에서는 문자열 배열을 단일 문자열로 조인하는 것에 대해 설명하지 않습니다. 문자열 배열 조인에 대한 자세한 내용은 String.Join 메서드를 참조하세요.

각 배열의 요소를 새 배열로 복사하기 전에 먼저 배열의 크기가 새 배열을 수용할 수 있을 정도가 되도록 배열을 초기화해야 합니다. 이 작업은 다음 두 가지 방법 중 한 가지로 수행할 수 있습니다.

  • 새 요소를 추가하기 전에 ReDim Preserve 문을 사용하여 배열을 동적으로 확장합니다. 이 방법은 가장 쉬운 방법이지만 큰 배열을 복사할 때 성능이 저하되고 메모리 소비가 과도하게 발생할 수 있습니다.
  • 새 큰 배열에 필요한 요소의 총 수를 계산한 다음 각 원본 배열의 요소를 추가합니다.

다음 예제에서는 두 번째 방법을 사용하여 각각 10개의 요소가 있는 4개의 배열을 단일 배열에 추가합니다.

Imports System.Collections.Generic
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim tasks As New List(Of Task(Of Integer()))
      ' Generate four arrays.
      For ctr = 0 To 3
         Dim value = ctr
         tasks.Add(Task.Run(Function()
                               Dim arr(9) As Integer
                               For ndx = 0 To arr.GetUpperBound(0)
                                  arr(ndx) = value
                               Next
                               Return arr
                            End Function))   
       Next
       Task.WaitAll(tasks.ToArray())
       ' Compute the number of elements in all arrays.
       Dim elements = 0
       For Each task In tasks
          elements += task.Result.Length
       Next
       Dim newArray(elements - 1) As Integer
       Dim index = 0
       For Each task In tasks
          Dim n = task.Result.Length
          Array.Copy(task.Result, 0, newArray, index, n)
          index += n
       Next 
      Console.WriteLine($"The new array has {newArray.Length} elements.")
   End Sub
End Module
' The example displays the following output:
'     The new array has 40 elements.

이 경우 원본 배열은 모두 작기 때문에 각 새 배열의 요소를 추가할 때 배열을 동적으로 확장할 수도 있습니다. 다음 예제에서는 해당 작업을 수행합니다.

Imports System.Collections.Generic
Imports System.Threading.Tasks

Module Example
   Public Sub Main()
      Dim tasks As New List(Of Task(Of Integer()))
      ' Generate four arrays.
      For ctr = 0 To 3
         Dim value = ctr
         tasks.Add(Task.Run(Function()
                               Dim arr(9) As Integer
                               For ndx = 0 To arr.GetUpperBound(0)
                                  arr(ndx) = value
                               Next
                               Return arr
                            End Function))   
       Next
       Task.WaitAll(tasks.ToArray())

       ' Dimension the target array and copy each element of each source array to it.
       Dim newArray() As Integer = {}
       ' Define the next position to copy to in newArray.
       Dim index = 0
       For Each task In tasks
          Dim n = Task.Result.Length
          ReDim Preserve newArray(newArray.GetUpperBound(0) + n)
          Array.Copy(task.Result, 0, newArray, index, n)
          index += n
       Next 
      Console.WriteLine($"The new array has {newArray.Length} elements.")
   End Sub
End Module
' The example displays the following output:
'     The new array has 40 elements.

배열의 대안으로 사용되는 컬렉션

배열은 고정된 개수의 강력한 형식 개체를 만들고 작업하는 데 가장 유용합니다. 컬렉션은 개체 그룹에 대해 작업하는 보다 유연한 방법을 제공합니다. ReDim을 사용하여 배열의 크기를 명시적으로 변경해야 하는 배열과 달리 컬렉션은 애플리케이션의 요구 사항이 변경되면 동적으로 확장 및 축소됩니다.

배열을 다시 조정하는 데 ReDim을 사용하는 경우 Visual Basic은 새 배열을 만들고 이전 배열을 해제합니다. 이 경우 실행 시간이 걸립니다. 따라서 작업하는 항목 수가 자주 변경되거나 필요한 항목의 최대 수를 예측할 수 없는 경우 컬렉션을 사용하여 성능을 개선할 수 있습니다.

일부 컬렉션의 경우 키를 사용하여 개체를 신속하게 검색할 수 있도록 컬렉션에 추가하는 모든 개체에 키를 할당할 수 있습니다.

컬렉션에 단일 데이터 형식의 요소만 포함된 경우 System.Collections.Generic 네임스페이스의 클래스 중 하나를 사용할 수 있습니다. 제네릭 컬렉션은 다른 데이터 형식을 추가할 수 없도록 형식 안전성을 적용합니다.

항목 컬렉션에 대한 자세한 내용은 컬렉션을 참조하세요.

용어 정의
Array Dimensions in Visual Basic 배열의 차수 및 차원을 설명합니다.
방법: Visual Basic에서 배열 변수 초기화 배열에 초기 값을 채우는 방법을 설명합니다.
방법: Visual Basic에서 배열 정렬 배열의 요소를 사전순으로 정렬하는 방법을 보여 줍니다.
방법: 한 배열에 다른 배열 할당 다른 배열 변수에 배열을 할당하는 규칙 및 단계를 설명합니다.
배열 문제 해결 배열에서 작업할 때 발생할 수 있는 몇 가지 일반적인 문제를 설명합니다.

참고 항목