배열
배열 데이터 구조에 형식이 동일한 변수를 여러 개 저장할 수 있습니다. 요소의 형식을 지정하여 배열을 선언합니다. 배열이 모든 형식의 요소를 저장하도록 하려는 경우 object
를 해당 형식으로 지정할 수 있습니다. C#의 통합 형식 시스템에서 사용자 정의 및 미리 정의된 참조 형식과 값 형식을 비롯한 모든 형식은 직접 또는 간접적으로 Object에서 상속합니다.
type[] arrayName;
배열은 참조 형식이므로 배열은 nullable 참조 형식일 수 있습니다. 요소 형식은 참조 형식일 수 있으므로 nullable 참조 형식을 보유하도록 배열을 선언할 수 있습니다. 다음 예제 선언에서는 배열 또는 요소의 null 허용 여부를 선언하는 데 사용되는 다른 구문을 보여 줍니다.
type?[] arrayName; // non nullable array of nullable element types.
type[]? arrayName; // nullable array of non-nullable element types.
type?[]? arrayName; // nullable array of nullable element types.
배열의 초기화되지 않은 요소는 해당 형식의 기본값으로 설정됩니다.
int[] numbers = new int[10]; // All values are 0
string[] messages = new string[10]; // All values are null.
Important
앞의 예제에서 형식이 null을 허용하지 않는 문자열의 배열인 string[]
경우에도 각 요소의 기본값은 null입니다. 배열을 null이 아닌 값으로 초기화하는 가장 좋은 방법은
배열에는 다음과 같은 속성이 있습니다.
- 배열은 단일 차원, 다차원 또는 가변일 수 있습니다.
- 차원 수는 배열 변수를 선언할 때 설정됩니다. 각 차원의 길이는 배열 인스턴스가 만들어질 때 설정됩니다. 이러한 값은 인스턴스의 수명 동안 변경할 수 없습니다.
- 가변 배열은 배열의 배열이며 각 멤버 배열의 기본값은
null
입니다. - 배열은 0으로 인덱싱됩니다.
n
요소는0
부터n-1
로 인덱싱됩니다. - 배열 요소 형식은 배열 형식을 비롯한 어떤 형식도 될 수 있습니다.
- 배열 형식은 추상 기본 형식에서 파생된 Array입니다. 모든 배열은 IList 및 IEnumerable을 구현합니다. foreach 문을 사용하여 배열을 반복할 수 있습니다. 단일 차원 배열은 IList<T> 및 IEnumerable<T>도 구현합니다.
배열 요소는 배열이 만들어질 때 알려진 값으로 초기화될 수 있습니다. C# 12부터 모든 컬렉션 형식은 컬렉션 식을 사용하여 초기화할 수 있습니다. 초기화되지 않은 요소는 기본값으로 설정됩니다. 기본값은 0비트 패턴입니다. 모든 참조 형식(null을 허용하지 않는 형식 포함)의 값은 null
입니다. 모든 값 형식에는 0비트 패턴이 있습니다. 이는 Nullable<T>.HasValue 속성이 false
이고 Nullable<T>.Value 속성이 정의되지 않았음을 의미합니다. .NET 구현에서 Value
속성은 예외를 throw합니다.
다음 예제에서는 단일 차원, 다차원 및 가변 배열을 만듭니다.
// Declare a single-dimensional array of 5 integers.
int[] array1 = new int[5];
// Declare and set array element values.
int[] array2 = [1, 2, 3, 4, 5, 6];
// Declare a two dimensional array.
int[,] multiDimensionalArray1 = new int[2, 3];
// Declare and set array element values.
int[,] multiDimensionalArray2 = { { 1, 2, 3 }, { 4, 5, 6 } };
// Declare a jagged array.
int[][] jaggedArray = new int[6][];
// Set the values of the first array in the jagged array structure.
jaggedArray[0] = [1, 2, 3, 4];
Important
이 문서의 많은 예에서는 컬렉션 식(대괄호 사용)을 사용하여 배열을 초기화합니다. 컬렉션 식은 .NET 8과 함께 제공되는 C# 12에서 처음 도입되었습니다. C# 12로 아직 업그레이드할 수 없는 경우 대신 배열을 사용하고 {
}
초기화합니다.
// Collection expressions:
int[] array = [1, 2, 3, 4, 5, 6];
// Alternative syntax:
int[] array2 = {1, 2, 3, 4, 5, 6};
1차원 배열
1차원 배열은 유사한 요소의 시퀀스입니다.
인덱스를 통해 요소에 액세스합니다.
인덱스는 시퀀스의 시퀀스 위치입니다. 배열의 첫 번째 요소는 인덱스 0
에 있습니다. 배열 요소 형식과 요소 수를 지정하는 new 연산자를 사용하여 1차원 배열을 만듭니다. 다음 예에서는 1차원 배열을 선언하고 초기화합니다.
int[] array = new int[5];
string[] weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
Console.WriteLine(weekDays[0]);
Console.WriteLine(weekDays[1]);
Console.WriteLine(weekDays[2]);
Console.WriteLine(weekDays[3]);
Console.WriteLine(weekDays[4]);
Console.WriteLine(weekDays[5]);
Console.WriteLine(weekDays[6]);
/*Output:
Sun
Mon
Tue
Wed
Thu
Fri
Sat
*/
첫 번째 선언은 array[0]
에서 array[4]
까지 5개의 정수로 구성된 초기화되지 않은 배열을 선언합니다. 배열의 요소는 요소 형식의 기본값(정수의 경우 0
)으로 초기화됩니다. 두 번째 선언은 문자열 배열을 선언하고 해당 배열의 7개 값을 모두 초기화합니다. 일련의 Console.WriteLine
문은 weekDay
배열의 모든 요소를 인쇄합니다. 1차원 배열의 경우 foreach
문은 인덱스 0으로 시작하고 인덱스 Length - 1
로 끝나는 늘어나는 인덱스 순서로 요소를 처리합니다.
1차원 배열을 인수로 전달
초기화된 1차원 배열을 메서드에 전달할 수 있습니다. 다음 예제에서는 문자열 배열이 초기화되고 문자열에 대한 DisplayArray
메서드에 인수로 전달됩니다. 메서드가 배열 요소를 표시합니다. 다음으로 ChangeArray
메서드는 배열 요소를 반대로 전환한 다음, ChangeArrayElements
메서드는 배열의 처음 세 요소를 수정합니다. 각 메서드가 반환된 후 DisplayArray
메서드는 배열을 값으로 전달해도 배열 요소가 변경되지 않는다는 것을 보여줍니다.
class ArrayExample
{
static void DisplayArray(string[] arr) => Console.WriteLine(string.Join(" ", arr));
// Change the array by reversing its elements.
static void ChangeArray(string[] arr) => Array.Reverse(arr);
static void ChangeArrayElements(string[] arr)
{
// Change the value of the first three array elements.
arr[0] = "Mon";
arr[1] = "Wed";
arr[2] = "Fri";
}
static void Main()
{
// Declare and initialize an array.
string[] weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
// Display the array elements.
DisplayArray(weekDays);
Console.WriteLine();
// Reverse the array.
ChangeArray(weekDays);
// Display the array again to verify that it stays reversed.
Console.WriteLine("Array weekDays after the call to ChangeArray:");
DisplayArray(weekDays);
Console.WriteLine();
// Assign new values to individual array elements.
ChangeArrayElements(weekDays);
// Display the array again to verify that it has changed.
Console.WriteLine("Array weekDays after the call to ChangeArrayElements:");
DisplayArray(weekDays);
}
}
// The example displays the following output:
// Sun Mon Tue Wed Thu Fri Sat
//
// Array weekDays after the call to ChangeArray:
// Sat Fri Thu Wed Tue Mon Sun
//
// Array weekDays after the call to ChangeArrayElements:
// Mon Wed Fri Wed Tue Mon Sun
다차원 배열
배열에 둘 이상의 차원이 있을 수 있습니다. 예를 들어 다음 선언은 4개의 배열을 만듭니다. 두 배열은 두 개의 차원을 가집니다. 두 배열에는 3차원이 있습니다. 처음 두 선언은 각 차원의 길이를 선언하지만 배열 값을 초기화하지 않습니다. 두 번째 두 선언에서는 이니셜라이저를 사용하여 다차원 배열의 각 요소 값을 설정합니다.
int[,] array2DDeclaration = new int[4, 2];
int[,,] array3DDeclaration = new int[4, 2, 3];
// Two-dimensional array.
int[,] array2DInitialization = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// Three-dimensional array.
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// Accessing array elements.
System.Console.WriteLine(array2DInitialization[0, 0]);
System.Console.WriteLine(array2DInitialization[0, 1]);
System.Console.WriteLine(array2DInitialization[1, 0]);
System.Console.WriteLine(array2DInitialization[1, 1]);
System.Console.WriteLine(array2DInitialization[3, 0]);
System.Console.WriteLine(array2DInitialization[3, 1]);
// Output:
// 1
// 2
// 3
// 4
// 7
// 8
System.Console.WriteLine(array3D[1, 0, 1]);
System.Console.WriteLine(array3D[1, 1, 2]);
// Output:
// 8
// 12
// Getting the total count of elements or the length of a given dimension.
var allLength = array3D.Length;
var total = 1;
for (int i = 0; i < array3D.Rank; i++)
{
total *= array3D.GetLength(i);
}
System.Console.WriteLine($"{allLength} equals {total}");
// Output:
// 12 equals 12
다차원 배열의 경우 요소는 가장 오른쪽 차원의 인덱스가 먼저 증가되고 다음 왼쪽 차원이 증가하는 방식으로 가장 왼쪽 인덱스까지 트래버스됩니다. 다음 예에서는 2D 배열과 3D 배열을 모두 열거합니다.
int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } };
foreach (int i in numbers2D)
{
System.Console.Write($"{i} ");
}
// Output: 9 99 3 33 5 55
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
foreach (int i in array3D)
{
System.Console.Write($"{i} ");
}
// Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
2D 배열에서는 왼쪽 인덱스를 행으로, 오른쪽 인덱스를 열로 생각할 수 있습니다.
그러나 다차원 배열에서 중첩 for 루프를 사용하면 배열 요소를 처리하는 순서를 더 강력하게 제어할 수 있습니다.
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
for (int i = 0; i < array3D.GetLength(0); i++)
{
for (int j = 0; j < array3D.GetLength(1); j++)
{
for (int k = 0; k < array3D.GetLength(2); k++)
{
System.Console.Write($"{array3D[i, j, k]} ");
}
System.Console.WriteLine();
}
System.Console.WriteLine();
}
// Output (including blank lines):
// 1 2 3
// 4 5 6
//
// 7 8 9
// 10 11 12
//
다차원 배열을 인수로 전달
초기화된 다차원 배열을 1차원 배열 전달과 동일한 방식으로 메서드에 전달합니다. 다음 코드는 2차원 배열을 해당 인수로 허용하는 인쇄 메서드의 부분 선언을 보여 줍니다. 다음 예제와 같이 한 단계로 새 배열을 초기화하고 전달할 수 있습니다. 다음 예제에서는 정수의 2차원 배열이 초기화되고 Print2DArray
메서드에 전달됩니다. 메서드가 배열 요소를 표시합니다.
static void Print2DArray(int[,] arr)
{
// Display the array elements.
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
System.Console.WriteLine("Element({0},{1})={2}", i, j, arr[i, j]);
}
}
}
static void ExampleUsage()
{
// Pass the array as an argument.
Print2DArray(new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } });
}
/* Output:
Element(0,0)=1
Element(0,1)=2
Element(1,0)=3
Element(1,1)=4
Element(2,0)=5
Element(2,1)=6
Element(3,0)=7
Element(3,1)=8
*/
가변 배열
가변 배열은 요소, 아마도 요소의 크기가 서로 다른 배열입니다. 가변 배열을 “배열의 배열”이라고도 합니다. 해당 요소는 참조 형식이며 null
로 초기화됩니다. 다음 예제에서는 가변 배열을 선언, 초기화 및 액세스하는 방법을 보여 줍니다. 첫 번째 예인 jaggedArray
는 하나의 문으로 선언됩니다. 포함된 각 배열은 후속 문에서 만들어집니다. 두 번째 예인 jaggedArray2
는 하나의 문에서 선언되고 초기화됩니다. 가변 배열과 다차원 배열을 함께 사용할 수 있습니다. 마지막 예인 jaggedArray3
은 크기가 서로 다른 세 개의 2차원 배열 요소를 포함하는 1차원 가변 배열의 선언 및 초기화입니다.
int[][] jaggedArray = new int[3][];
jaggedArray[0] = [1, 3, 5, 7, 9];
jaggedArray[1] = [0, 2, 4, 6];
jaggedArray[2] = [11, 22];
int[][] jaggedArray2 =
[
[1, 3, 5, 7, 9],
[0, 2, 4, 6],
[11, 22]
];
// Assign 77 to the second element ([1]) of the first array ([0]):
jaggedArray2[0][1] = 77;
// Assign 88 to the second element ([1]) of the third array ([2]):
jaggedArray2[2][1] = 88;
int[][,] jaggedArray3 =
[
new int[,] { {1,3}, {5,7} },
new int[,] { {0,2}, {4,6}, {8,10} },
new int[,] { {11,22}, {99,88}, {0,9} }
];
Console.Write("{0}", jaggedArray3[0][1, 0]);
Console.WriteLine(jaggedArray3.Length);
가변 배열의 요소를 사용하려면 먼저 초기화해야 합니다. 각 요소는 그 자체로 배열입니다. 이니셜라이저를 사용하여 배열 요소를 값으로 채우는 것도 가능합니다. 이니셜라이저를 사용하면 배열 크기가 필요하지 않습니다.
이 예제에서는 요소 자체가 배열인 배열을 작성합니다. 각 배열 요소의 크기가 서로 다릅니다.
// Declare the array of two elements.
int[][] arr = new int[2][];
// Initialize the elements.
arr[0] = [1, 3, 5, 7, 9];
arr[1] = [2, 4, 6, 8];
// Display the array elements.
for (int i = 0; i < arr.Length; i++)
{
System.Console.Write("Element({0}): ", i);
for (int j = 0; j < arr[i].Length; j++)
{
System.Console.Write("{0}{1}", arr[i][j], j == (arr[i].Length - 1) ? "" : " ");
}
System.Console.WriteLine();
}
/* Output:
Element(0): 1 3 5 7 9
Element(1): 2 4 6 8
*/
암시적으로 형식화된 배열
배열 인스턴스의 형식이 배열 이니셜라이저에 지정된 요소에서 유추되는 암시적으로 형식화된 배열을 만들 수 있습니다. 암시적으로 형식화된 변수에 대한 규칙은 암시적으로 형식화된 배열에도 적용됩니다. 자세한 내용은 암시적으로 형식화된 지역 변수를 참조하세요.
다음 예에서는 암시적으로 형식화된 배열을 만드는 방법을 보여 줍니다.
int[] a = new[] { 1, 10, 100, 1000 }; // int[]
// Accessing array
Console.WriteLine("First element: " + a[0]);
Console.WriteLine("Second element: " + a[1]);
Console.WriteLine("Third element: " + a[2]);
Console.WriteLine("Fourth element: " + a[3]);
/* Outputs
First element: 1
Second element: 10
Third element: 100
Fourth element: 1000
*/
var b = new[] { "hello", null, "world" }; // string[]
// Accessing elements of an array using 'string.Join' method
Console.WriteLine(string.Join(" ", b));
/* Output
hello world
*/
// single-dimension jagged array
int[][] c =
[
[1,2,3,4],
[5,6,7,8]
];
// Looping through the outer array
for (int k = 0; k < c.Length; k++)
{
// Looping through each inner array
for (int j = 0; j < c[k].Length; j++)
{
// Accessing each element and printing it to the console
Console.WriteLine($"Element at c[{k}][{j}] is: {c[k][j]}");
}
}
/* Outputs
Element at c[0][0] is: 1
Element at c[0][1] is: 2
Element at c[0][2] is: 3
Element at c[0][3] is: 4
Element at c[1][0] is: 5
Element at c[1][1] is: 6
Element at c[1][2] is: 7
Element at c[1][3] is: 8
*/
// jagged array of strings
string[][] d =
[
["Luca", "Mads", "Luke", "Dinesh"],
["Karen", "Suma", "Frances"]
];
// Looping through the outer array
int i = 0;
foreach (var subArray in d)
{
// Looping through each inner array
int j = 0;
foreach (var element in subArray)
{
// Accessing each element and printing it to the console
Console.WriteLine($"Element at d[{i}][{j}] is: {element}");
j++;
}
i++;
}
/* Outputs
Element at d[0][0] is: Luca
Element at d[0][1] is: Mads
Element at d[0][2] is: Luke
Element at d[0][3] is: Dinesh
Element at d[1][0] is: Karen
Element at d[1][1] is: Suma
Element at d[1][2] is: Frances
*/
앞의 예에서 암시적으로 형식화된 배열의 경우 초기화 문의 왼쪽에 대괄호가 사용되지 않는 것을 확인합니다. 또한 가변 배열은 1차원 배열과 마찬가지로 new []
를 사용하여 초기화됩니다.
배열이 포함된 무명 형식을 만드는 경우 해당 형식의 개체 이니셜라이저에서 배열을 암시적으로 형식화해야 합니다. 다음 예에서 contacts
는 각각 PhoneNumbers
라는 배열이 포함된 무명 형식의 암시적으로 형식화된 배열입니다.
var
키워드는 개체 이니셜라이저 내에서 사용되지 않습니다.
var contacts = new[]
{
new
{
Name = "Eugene Zabokritski",
PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
},
new
{
Name = "Hanying Feng",
PhoneNumbers = new[] { "650-555-0199" }
}
};
.NET