숏컷 코드
// 배열 — 고정 길이
int[] scores = { 85, 90, 78 };
string[] slots = new string[3]; // 초기값 null
int first = scores[0]; // 인덱스 접근
// List<T> — 가변 길이
var names = new List<string> { "Mina", "Jin" };
names.Add("Sol");
names.Remove("Jin");
int count = names.Count;문법
어떤 컬렉션을 먼저 떠올리면 되나
가장 먼저 구분할 것은 배열 T[] 과 List<T> 입니다.
int[] fixedScores = { 85, 90, 78 }; // 길이 고정
var dynamicScores = new List<int> { 85, 90 }; // 길이 변경 가능- 크기가 처음부터 정해져 있고 바뀌지 않으면 배열
- 추가/삭제가 자연스럽게 들어오면
List<T> - 둘 다 인덱스로 읽을 수 있지만, 길이와 확장 방식이 다릅니다
배열 — 연속된 고정 메모리
배열은 연속된 메모리 블록에 고정 개수의 요소를 저장합니다. new int[5]를 선언하면 5개 int에 해당하는 메모리가 연속으로 할당됩니다. 이 연속성 때문에 인덱스 접근(arr[i])은 O(1)로 매우 빠릅니다.
int[] arr = new int[5]; // 모두 0으로 초기화
int[] arr2 = { 1, 2, 3 }; // 선언과 동시에 초기화
int[] arr3 = new int[] { 1, 2, 3 }; // 동일한 의미
// 길이와 범위
Console.WriteLine(arr2.Length); // 3
Console.WriteLine(arr2[0]); // 1 (0-based index)
Console.WriteLine(arr2[^1]); // 3 (마지막 요소, C# 8+)
Console.WriteLine(arr2[1..]); // {2, 3} (슬라이싱, C# 8+)배열을 초기화하면 숫자 타입은 0, bool은 false, 참조 타입은 null로 채워집니다.
List<T> — 내부적으로 배열을 동적으로 확장
List<T>는 내부에 배열을 가지고 있습니다. Add()를 호출할 때 내부 배열이 꽉 차면 2배 크기의 새 배열을 할당하고 복사합니다. 이것이 capacity 재할당입니다. 추가할 항목 수를 미리 알면 new List<T>(capacity)로 초기 크기를 지정해 재할당을 줄일 수 있습니다.
var list = new List<int>(100); // capacity 100으로 시작 — 재할당 방지
list.Add(1);
list.AddRange(new[] { 2, 3, 4 }); // 여러 항목 한 번에 추가
list.Insert(0, 0); // 특정 위치에 삽입 — O(n)
list.Remove(3); // 값으로 제거 — O(n)
list.RemoveAt(0); // 인덱스로 제거 — O(n)
bool has = list.Contains(2); // O(n)
int idx = list.IndexOf(2); // -1이면 없음
list.Sort(); // 정렬
list.Reverse(); // 역순다차원 배열과 가변 배열
다차원 배열은 행렬처럼 2개 이상의 차원을 가집니다. 가변 배열(jagged array) 은 각 행의 길이가 다를 수 있는 배열의 배열입니다.
// 2차원 배열 (직사각형)
int[,] matrix = new int[3, 4]; // 3행 4열
matrix[0, 0] = 1;
// 가변 배열 (각 행 길이가 다름)
int[][] jagged = new int[3][];
jagged[0] = new int[] { 1, 2 };
jagged[1] = new int[] { 3, 4, 5 };
jagged[2] = new int[] { 6 };배열과 List<T> 변환
int[] arr = { 1, 2, 3 };
List<int> list = arr.ToList(); // 배열 → List
int[] arr2 = list.ToArray(); // List → 배열
// IEnumerable<T>에서 변환
int[] filtered = list.Where(x => x > 1).ToArray();체크포인트
| 구조 | 특징 | 크기 | 인덱스 접근 |
|---|---|---|---|
배열 T[] | 고정 길이, 연속 메모리 | Length | O(1) |
List<T> | 가변 길이, 내부 배열 기반 | Count | O(1) |
| 선택 기준 | 크기 변경 없음 → 배열, 추가/삭제 → List<T> | ||
Add, Remove | O(1) 평균, O(n) 최악 (재할당/이동) |
int[] arr = { 1, 2, 3 };
var list = new List<int> { 1, 2, 3 };
// ❌ 배열은 Add가 없다
// arr.Add(4);
// ✅ List<T>는 길이를 늘릴 수 있다
list.Add(4);주의할 점
List<T>의 Insert()와 Remove()는 O(n) 입니다. 중간에 자주 삽입/삭제하는 경우 LinkedList<T>나 다른 자료구조를 검토하세요.
배열의 범위 초과 접근은 IndexOutOfRangeException을 발생시킵니다. arr[arr.Length - 1] 대신 C# 8+의 인덱스 연산자 arr[^1]을 쓰면 실수를 줄일 수 있습니다.
참고 링크
2 sources