CodeGym /행동 /C# SELF /컬렉션: OrderedDictionary

컬렉션: OrderedDictionary 와 ReadOnlySet

C# SELF
레벨 34, 레슨 1
사용 가능

1. 컬렉션 OrderedDictionary

.NET은 항상 풍부한 표준 라이브러리로 유명했지만, 개발자 인생에서 타협해야 하는 순간이 있었지: 추가 순서를 기억하는 딕셔너리가 필요하거나, 변경 불가능한 유니크 값 집합이 필요할 때. .NET 9 이전에는 외부 라이브러리를 쓰거나 직접 만들어야 했어 (누군가는 GitHub에서 OrderedDictionary를 복붙하기도 했지 — 쉿, 아무한테도 말 안 할게).

.NET 9가 나오면서 새로운 제네릭 컬렉션이 생겼어 — 이제 꼼수는 잊어도 돼! 가장 쓸만한 두 가지, OrderedDictionary<TKey, TValue> 와 ReadOnlySet<T>를 자세히 볼게.

1. OrderedDictionary란?

OrderedDictionary는 딕셔너리와 리스트의 하이브리드야. "키-값" 쌍을 저장하는 건 Dictionary<TKey, TValue>랑 똑같은데, 요소의 순서가 추가한 순서랑 똑같이 유지돼. 이건 사용자가 입력한 순서대로 순회해야 하거나, 순서가 비즈니스 로직에 영향을 줄 때(예: 리포트 출력, 데이터 직렬화, 설정 생성 등)에 특히 중요해.

비유

일반 딕셔너리가 그냥 막 집어넣고 꺼내는 수납장이면, OrderedDictionary는 정리정돈 잘 된 서랍장이야. 뭐가 먼저 들어갔는지, 나중에 들어갔는지 항상 알 수 있지.

2. Dictionary와의 주요 차이점

  • Dictionary: 요소 순서가 보장되지 않아 (항상 똑같아 보여도 — 믿지 마, 그건 착각이야!).
  • OrderedDictionary: 추가한 순서 그대로 저장돼.

3. 문법과 주요 메서드

기본 사용 예시:


using System.Collections.Generic;

var od = new OrderedDictionary<string, int>();
od.Add("Ivan", 5);
od.Add("Svetlana", 8);
od.Add("Alex", 3);

// 추가 순서대로 순회:
foreach (var pair in od)
{
    Console.WriteLine($"{pair.Key}: {pair.Value}");
}

출력:

Ivan: 5
Svetlana: 8
Alex: 3

똑같은 예제를 일반 딕셔너리로 하면 순서가 다를 수 있어. 근데 OrderedDictionary는 항상 추가한 순서대로 나와.

OrderedDictionary는 일반 딕셔너리와 같은 인터페이스를 구현해:

  • IDictionary<TKey, TValue>
  • IReadOnlyDictionary<TKey, TValue>
  • IEnumerable<KeyValuePair<TKey, TValue>>

4. 인덱스와 키로 접근

특징: OrderedDictionary는 키로도, 인덱스로도 접근할 수 있어!


// 이름(키)로:
int svetlanaScore = od["Svetlana"]; // 8

// 인덱스로:
var firstEntry = od.ElementAt(0); // KeyValuePair<string, int>("Ivan", 5)

5. 업데이트와 삭제

이미 있는 키로 새 요소를 추가하면 예외가 발생해. 값을 바꾸고 싶으면 인덱서를 써:

od["Ivan"] = 10; // 기존 값만 바뀌고, 순서는 그대로야

삭제는 키로도, 인덱스로도 가능해:


od.Remove("Svetlana");
od.RemoveAt(0);      // "Ivan" 삭제

6. 구조 시각화


flowchart LR
    A("0: Ivan - 5")
    B("1: Svetlana - 8")
    C("2: Alex - 3")
    A --> B --> C
각 노드는 키-값 쌍이고, 화살표는 추가 순서를 보여줘.

7. 함정과 실수

많은 개발자들이 Dictionary<TKey, TValue>를 쓰면서 순서를 기대하는데 — 그건 함정이야! 어떤 데이터에선 순서가 유지돼도, 다음엔 바뀔 수 있어 (.NET 버전이나 플랫폼이 달라지면 특히 그래).

OrderedDictionary는 순서를 저장하느라 일부 연산(중간에 삽입, 삭제 등)이 약간 느릴 수 있지만, 대부분의 경우 장점이 더 커.

인덱스로 자주 접근해야 한다면 OrderedDictionary가 딱이고, 키로만 빠르게 찾고 순서가 중요하지 않으면 그냥 딕셔너리를 써.

8. 앱에서의 실전 예시

예를 들어, 직원과 부서를 관리하는 앱에서 직원이 추가된 순서대로 리포트를 출력해야 한다고 해보자:


var employeeScores = new OrderedDictionary<string, int>();
employeeScores.Add("Петр", 100);
employeeScores.Add("Анна", 150);
employeeScores.Add("Виктория", 80);

// 이제 리포트는 항상 원하는 순서로 나와:
foreach (var pair in employeeScores)
{
    Console.WriteLine($"{pair.Key}: {pair.Value} 점");
}

2. 컬렉션 ReadOnlySet<T>

1. ReadOnlySet란?

ReadOnlySet<T>는 변경 불가능(immutable)한 유니크 값 집합이야. 예전엔 "읽기 전용 set"을 만들려면 .ToHashSet()으로 복사하거나 직접 래퍼를 만들어야 했지. 이제는 생성 후 요소를 추가하거나 삭제할 수 없는 컬렉션이 생겼어. 이건 코드의 안전성을 높이고, 외부에서 실수로 데이터를 바꾸는 걸 막아줘.

비유

이건 마치 유니크한 이름을 적어놓고... 페이지를 코팅해버린 노트야. 아무도 더 추가하거나, 찢거나, 고칠 수 없어.

2. ReadOnlySet 만들기

가장 간단한 방법은 확장 메서드를 쓰는 거야:


var colors = new[] { "Red", "Green", "Blue", "Green" };
var readOnlyColors = colors.ToReadOnlySet();

// 이제 여기엔 오직 유니크 값만 있고, 바꿀 수 없어:
foreach (var color in readOnlyColors)
    Console.WriteLine(color);

출력:

Red
Green
Blue

직접 생성자도 쓸 수 있어(필요하다면):


var set = new ReadOnlySet<int>(new[] {1, 2, 2, 3, 5, 1}); // 결국 1,2,3,5만 남아

Microsoft Docs의 ReadOnlySet

3. 주요 속성과 메서드

  • 읽기 전용 (immutable)
  • Count — 요소 개수
  • Contains(item) — 요소 포함 여부 확인
  • LINQ 쿼리 지원 (IEnumerable<T>)
  • 빠른 검색, 추가/삭제/초기화는 불가

예시:


if (readOnlyColors.Contains("Red"))
    Console.WriteLine("빨간색이 리스트에 있어!");

이렇게 하면 안 돼:


// 컴파일 에러!
readOnlyColors.Add("Yellow");

4. 어디에 쓸까?

외부에 집합을 넘겨주고 싶지만, 누가 실수(혹은 악의적으로)로 바꾸는 걸 막고 싶을 때 자주 써. 예를 들면:

  • 지원하는 사용자 역할 목록 반환
  • 허용된 파일 확장자 목록
  • 변경 불가한 유니크 설정 파라미터 목록

우리 앱 예시: 허용된 부서 목록이 있다고 해보자:


public static ReadOnlySet<string> Departments { get; } =
    new[] { "Кадры", "Разработка", "Бухгалтерия" }.ToReadOnlySet();

이제 외부에서 부서 목록을 바꿀 수 없어.

5. 시각화: 일반 HashSet과의 차이


graph LR
    A[HashSet] -- Add/Remove/Contains --> B((Elements))
    C[ReadOnlySet] -- Only Contains --> D((Elements))
HashSet은 변경 가능, ReadOnlySet은 절대 안 돼!

3. OrderedDictionary vs. ReadOnlySet: 차이점 표

컬렉션 쌍 저장? 순서 보장 변경 가능 키로 검색 인덱스로 검색 사용 예시
OrderedDictionary 네 "키-값" 네 네 네 네 맵, 설정, 리포트
ReadOnlySet 아니, 값만 아니 아니 네 아니 안전한 집합, 상수
HashSet 아니, 값만 아니 네 네 아니 수정 가능한 집합
Dictionary 네 "키-값" 아니 네 네 아니 순서 상관없는 맵
2
과제
C# SELF, 레벨 34, 레슨 1
잠금
인덱스로 접근하고 OrderedDictionary에서 요소 삭제하기
인덱스로 접근하고 OrderedDictionary에서 요소 삭제하기
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION