C#LAB
C# 1.7 · 1부. 기초

배열과 컬렉션 기초

값을 여럿 담는 Array 와 List 를 다룹니다.

예상 학습 시간 14분 실행 단추가 있는 예제는 고쳐서 실행해 볼 수 있습니다 난이도 입문
개념 설명

값을 여럿 담아 두기

학생 서른 명의 점수를 다루려고 변수를 서른 개 만들 수는 없습니다. 배열컬렉션은 값을 하나의 이름 아래 여럿 담아 두고, 번호나 순서로 꺼내 쓰게 해 줍니다. 앞 단원의 foreach 가 탐색하던 대상이 바로 이것입니다.

가장 먼저 만나는 두 가지는 이렇게 다릅니다.

  • 배열(int[]) — 만들 때 크기를 정하고 그 뒤로 바꾸지 못합니다. 몇 개인지 이미 알고 있고 그 수가 변하지 않을 때 알맞습니다.
  • 리스트(List<int>) — 담고 빼는 대로 크기가 저절로 늘고 줍니다. 몇 개가 될지 모를 때 사용합니다.

둘 다 번호는 0부터 셉니다. 세 개짜리의 번호는 0·1·2 이며, 3을 넣으면 없는 자리를 건드려 실행 중에 예외가 납니다.

최소 예제 · 편집 가능

배열 만들고 꺼내기

아래 코드는 브라우저 안에서 실제로 실행됩니다. 고쳐서 눌러 보셔도 됩니다.

Program.cs
string[] fruits = { "사과", "바나나", "포도" };

Console.WriteLine(fruits.Length);
Console.WriteLine(fruits[0]);

fruits[2] = "딸기";
Console.WriteLine(fruits[2]);
출력
3 사과 딸기

코드는 고쳐서 실행해 볼 수 있습니다. 처음 누를 때만 실행기를 내려받느라 잠시 걸립니다. 적은 코드는 서버로 나가지 않습니다.

크기는 못 바꾸지만 안에 담긴 값은 바꿀 수 있습니다. 위에서 fruits[2] 를 딸기로 갈아 끼운 것처럼, 자리는 그대로 두고 그 자리의 값만 바꾸는 것은 됩니다. 반면 네 번째 자리를 새로 만들 수는 없습니다.

상세 사용법

배열을 만드는 세 가지 방법

// ① 크기만 정하기 — 숫자는 0, 문자열은 null 로 채워집니다
int[] a = new int[3];

// ② 값을 늘어놓기 — 크기는 값의 수로 정해집니다
int[] b = { 10, 20, 30 };

// ③ 컬렉션 식 (C# 12.0+)
int[] c = [10, 20, 30];

②는 선언과 동시에만 됩니다. 이미 만들어 둔 변수에 나중에 b = { 1, 2 }; 라고 적으면 컴파일되지 않습니다. 그때는 new int[] { 1, 2 } 처럼 적거나, C# 12.0부터라면 ③의 대괄호를 사용하면 됩니다.

크기가 변하는 리스트

List<int> 의 꺾쇠 안에는 무엇을 담을지 적습니다. 이렇게 담을 타입을 밖에서 정해 주는 방식을 제네릭이라고 하며, 자세한 것은 3부에서 봅니다. 지금은 List<string> 이 문자열을 담는 리스트라는 정도로 충분합니다.

멤버하는 일예시
Add끝에 하나 더하기list.Add("사과");
Insert정한 자리에 끼워 넣기list.Insert(0, "포도");
Remove그 값을 찾아 하나 빼기list.Remove("사과");
RemoveAt번호로 빼기list.RemoveAt(0);
Contains들어 있는지 묻기list.Contains("포도")
Count지금 몇 개인지list.Count

개수를 묻는 이름이 서로 다릅니다. 배열은 Length, 리스트는 Count 입니다. 자주 헷갈리는 자리이고, 잘못 적으면 컴파일 오류로 걸리므로 그때 바꿔 주면 됩니다.

배열 — 크기 고정
string[] names = new string[2];

names[0] = "민준";
names[1] = "서연";
// names[2] 는 예외

Console.WriteLine(names.Length);
리스트 — 크기 변함
var names = new List<string>();

names.Add("민준");
names.Add("서연");
names.Add("지호");   // 얼마든지

Console.WriteLine(names.Count);

뒤에서 세기와 잘라 내기

C# 8.0부터는 끝에서부터 번호를 셀 수 있습니다. ^1 이 마지막이며, 개수에서 1을 빼는 계산을 직접 하지 않아도 됩니다. 두 점(..)으로 일부만 잘라 낼 수도 있습니다.

int[] n = { 10, 20, 30, 40, 50 };

n[^1]      // 50 — 마지막
n[1..3]   // { 20, 30 } — 1번부터 3번 앞까지
n[2..]    // { 30, 40, 50 } — 2번부터 끝까지

잘라 내는 범위의 뒤쪽 번호는 포함되지 않습니다. 1..3 은 1번과 2번, 두 개입니다. for 문의 조건이 < 인 것과 같은 셈법입니다.

버전 배지

이 문법, 몇 버전부터 사용할 수 있나요

1.0
2.0
3.0
5.0
6.0
8.0
9.0
12.0
14.0
  • 1.0배열
  • 2.0제네릭 — List<T> 가 여기서 나왔습니다
  • 3.0컬렉션 이니셜라이저 — new List<int> { 1, 2 }
  • 8.0인덱스(^1) · 범위(1..3)
  • 12.0컬렉션 식 — [1, 2, 3]
C# 2.0+

배열은 처음부터 있었지만 List<int> 는 C# 2.0의 제네릭과 함께 나왔습니다. 그 전에는 무엇이든 담기는 ArrayList 를 사용했는데, 꺼낼 때마다 타입을 되돌려 밝혀야 했고 엉뚱한 것이 섞여 있어도 실행 전에 걸리지 않았습니다. 지금 코드에서 ArrayList 를 만난다면 아주 오래된 것입니다.

실습 문제

직접 해보기

1. 점수의 평균 구하기 난이도 하

int[] scores = { 80, 95, 70, 88 }; 의 평균을 구해 출력해보세요. 결과가 83.25 로 나와야 합니다.

합계는 정수, 개수도 정수입니다. 그대로 나누면 83 이 나오므로 1.4 단원에서 본 것처럼 한쪽을 실수로 바꿔야 합니다.
int[] scores = { 80, 95, 70, 88 }; int sum = 0; foreach (int s in scores) { sum += s; } Console.WriteLine((double)sum / scores.Length);
2. 중복 없이 담기 난이도 중

string[] input = { "사과", "포도", "사과", "딸기" }; 를 탐색하면서, 아직 담기지 않은 것만 List<string> 에 넣어보세요. 결과는 세 개가 됩니다.

이미 들어 있는지 묻는 것은 Contains 입니다. 앞에 ! 를 붙이면 "들어 있지 않으면" 이 됩니다.
string[] input = { "사과", "포도", "사과", "딸기" }; var result = new List<string>(); foreach (string s in input) { if (!result.Contains(s)) { result.Add(s); } } Console.WriteLine(result.Count); // 3
요약
  • 배열은 크기가 고정이고, 리스트는 담는 대로 늘고 줍니다.
  • 번호는 0부터입니다. 배열의 크기가 3이면 마지막 번호는 2입니다.
  • 개수를 묻는 이름이 다릅니다 — 배열은 Length, 리스트는 Count.
  • ^1 은 마지막, 1..3 은 1번부터 3번 앞까지입니다.

C# 버전별 변경 이력 에서 각 버전이 무엇을 더했는지 볼 수 있습니다.