[로봇활용_11주차] C# 인덱서(Indexer)

최윤호·2025년 10월 18일
post-thumbnail

클래스를 배열처럼 다루는 방법

혹시 C#에서 컬렉션을 다루면서 이런 생각이 들지 않으셨나요?

"와, 이거 정말 편하다! 내가 직접 만든 클래스도 이렇게
배열이나 딕셔너리처럼 데이터를 다룰 수 있으면 얼마나 좋을까?"

놀랍게도, C#은 바로 그 기능도 제공합니다! 인덱서(Indexer)를 사용하면
우리가 만든 객체를 마치 배열처럼 인덱스로 접근할 수 있게 만들 수 있습니다.

1)인덱서(Indexer)란?

인덱서(Indexer)는 클래스, 구조체, 인터페이스의 객체를 배열처럼
[ ]를 사용하여 인덱스로 접근할 수 있게 특별한 종류의 속성(Property)입니다.
인덱서는 메서드처럼 매개변수의 타입이나 개수를 다르게 하여 오버로딩할 수 있습니다.

비유: 도서관의 사서

우리가 도서관의 사서에게 "컴퓨터 과학 섹션의 세 번째 책 주세요!"
(library[ComputerScience, 3])라고 요청할 수 있습니다.
사서는 이 요청을 해석해서 실제 책장 어디에 있는 책을 가져다주죠.
우리는 책의 위치를 몰라도, '분류''번호'라는 인덱스만으로 책에 접근할 수 있습니다.
인덱서는 이 사서처럼, 외부의 요청을 내부의 실제 데이터로 연결해 주는 역할을 합니다.

속성(Property)과의 비교

인덱서는 속성과 거의 똑같이 getset접근자를 가집니다.
가장 큰 차이점은, 속성은 '이름'을 가지지만 인덱서는
this키워드를 이름으로 사용하고 [ ]매개변수를 받는다는 점입니다.

구분속성(Property)인덱서(Indexer)
선언public int MyProperty { get; set; }public int this[int index] { get; set; }
호출obj.MyProperty = 10;obj[0] = 10;

2)나만의 인덱서 만들기

학생들의 성적을 관리하는 클래스를 직접 만들어보며 인덱서를 구현해 봅시다.
내부적으로는 딕셔너리를 사용하여 데이터를 저장하겠지만,
외부에서는 이 사실을 숨기고 오직 이름(인덱스)만으로 점수에 접근하게 할 겁니다.

[코드]

using System;
using System.Linq; // ElementAt 메서드를 사용하려면 필요합니다.
using System.Collections.Generic; // 딕셔너리를 사용하려면 필요합니다.

public class Gradebook
{
    // 1. 실제 데이터는 private Dictionary에 안전하게 보관 (내부 구현)
    private Dictionary<string, int> _scores = new Dictionary<string, int>();

    // 2. 인덱서(Indexer) 정의
    public int this[string studentName]
    {
        // get 접근자: "grades[이름]"으로 점수를 읽으려 할 때 호출됨
        get
        {
            // 해당 학생이 존재하지 않을 경우를 대비해 안전하게 접근
            if (_scores.TryGetValue(studentName, out int score))
            {
                return score;
            }
            else
            {
                // 학생이 없으면 0점 또는 예외를 반환할 수 있음
                Console.WriteLine($"{studentName} 학생의 정보가 없습니다.");
                return 0;
            }
        }

        // set 접근자: "grades[이름] = 점수"로 값을 할당할 때 호출됨
        set
        {
            // 'value' 키워드는 할당하려는 값(점수)을 의미
            if (value >= 0 && value <= 100)
            {
                // 학생 이름이 이미 있으면 점수 수정, 없으면 새로 추가
                _scores[studentName] = value;
            }
            else
            {
                Console.WriteLine("유효하지 않은 점수입니다 (0 ~ 100).");
            }
        }
    }

    public int this[int index]
    {
        get
        {
            // 내부 Dictionary를 List로 변환하여 순서대로 접근
            if (index >= 0 && index < _scores.Count)
            {
                // LINQ를 사용하여 N번째 요소의 값을 가져옴
                return _scores.ElementAt(index).Value;
            }
            else
            {
                return -1; // 잘못된 인덱스
            }
        }
    }
}

class Program
{
    static void Main()
    {
        Gradebook myGrades = new Gradebook();

        // 1. set 접근자 호출: 점수 할당
        myGrades["홍길동"] = 95;
        myGrades["김철수"] = 88;
        myGrades["이영희"] = 101; // 유효성 검사에 걸림

        // 2. get 접근자 호출: 점수 조회
        Console.WriteLine($"홍길동의 점수: {myGrades["홍길동"]}");
        Console.WriteLine($"김철수의 점수: {myGrades["김철수"]}");
        Console.WriteLine($"이한결의 점수: {myGrades["이한결"]}"); // 존재하지 않는 학생

        // 3. 정수 인덱서를 통한 점수 조회
        Console.WriteLine($"첫 번째 학생의 점수: {myGrades[0]}");
    }
}

[실행 결과]

유효하지 않은 점수입니다 (0 ~ 100).
홍길동의 점수: 95
김철수의 점수: 88
이한결 학생의 정보가 없습니다.
이한결의 점수: 0
첫 번째 학생의 점수: 95

3)정리

인덱서는 C#의 사용성을 극적으로 향상하게 시키는 강력한 도구입니다.

인덱서의 장점설명
직관적인 문법객체를 배열이나 딕셔너리처럼 자연스럽게 사용할 수 있습니다.
캡슐화내부의 복잡한 데이터 구조를 숨기고, 외부에 일관된 접근 방식을 제공합니다.
유연성int, string 등 다양한 타입의 인덱스를 사용할 수 있으며, 오버로딩도 가능합니다.
profile
🚀 미래의 엔지니어를 꿈꾸는 훈련생의 기록 📝

0개의 댓글