[C#] 21. 인덱서(Indexer)를 사용하는 방법


Study/C#  2020. 7. 31. 18:00

안녕하세요. 명월입니다.


이 글은 C#에서 인덱서(Indexer)를 사용하는 방법에 대한 글입니다.


C#에서는 다른 언어에는 없는 재미있는 구문이 몇 개 있습니다. 그 중 하나가 이 인덱서(Indexer)입니다.

인덱서(Indexer)는 간단하게 말해서 배열같은 구문을 함수를 통해서 결과를 반환하는 것입니다. 프로퍼티와 비슷하게 생겼습니다만, 프로퍼티는 함수를 변수처럼 사용하는 문법이라고 하면 인덱서는 함수를 배열처럼 사용하는 문법이라고 생각하면 됩니다.

using System;
using System.Collections.Generic;

namespace Example
{
  // Indexer 예제 클래스
  class Node
  {
    // 맴버 변수
    private List<string> data = new List<string>();
    // 이것이 인덱서 문법이다.
    // 반환형과 함수명 자리에는 this를 넣고, 배열같이 대괄호로 데ㅇ이터를 받는다.
    public int this[string keyword]
    {
      // 인덱서의 get입니다.
      get
      {
        // 해당 키워드의 위치를 반환한다.
        for (int i = 0; i < data.Count; i++)
        {
          // 키워드와 맴버 변수 리스트의 객체 아이템과 같은 값이면
          if (string.Equals(data[i], keyword))
          {
            // 위치 반환
            return i;
          }
        }
        // 키워드가 없으면 -1를 반환
        return -1;
      }
      // 인덱서의 set입니다.	
      set
      {
        // 리스트에서 해당 키워드를 제거
        data.Remove(keyword);
        // 리스트에 index에 해당하는 위치에 키워드를 추가
        data.Insert(value, keyword);
      }
    }
    // 출력 함수
    public void Print()
    {
      // 맴버 변수 리스트 순서대로 
      foreach (var d in this.data)
      {
        // 콘솔 출력한다.
        Console.WriteLine(d);
      }
    }
  }
  class Program
  {
    // 실행 함수
    static void Main(string[] args)
    {
      // Node 인스턴스 생성
      Node node = new Node();
      // 인덱서를 이용하기 때문에 마치 배열처럼 들어간다.
      node["Hello"] = 0;
      node["World"] = 1;
      // 콘솔 출력
      node.Print();
      // 개행
      Console.WriteLine();
      // 인덱서 set을 통해서 Hello의 배열 위치를 바꾼다.
      node["Hello"] = 1;
      // 인덱서 get을 통해서 Hello의 배열 위치를 확인한다.
      Console.WriteLine(node["Hello"]);
      // 개행
      Console.WriteLine();
      // 콘솔 출력
      node.Print();
      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadKey();
    }
  }
}

위 예제를 보시면 제가 Node라는 클래스에 인덱서(Indexer)를 만들었습니다.

인덱서는 프로퍼티 처럼 배열의 값을 받는 자료형과 입력하는 자료형을 설정하고 함수명 자리에는 this를 넣습니다.

그리고 배열처럼 사용하기 때문에 배열 안의 자료형과 파라미터 형을 넣습니다.


Main의 실행 함수에서 node[string] = int형으로 값으로 호출하면 set이 호출이 됩니다. 그리고 node[string]을 호출하면 get 함수가 호출이 됩니다.

프로퍼티와 비슷한 구문으로 인덱서에서의 접근 제한자 설정은 기본 get 함수이고 set만 별도로 설정할 수 있습니다.

using System;
using System.Collections.Generic;

namespace Example
{
  // Indexer 예제 클래스
  class Node
  {
    // 맴버 변수
    private List<string> data = new List<string>();
    // 생성자 (가변 파라미터로 데이터를 받는다.)
    public Node(params string[] datas)
    {
      for (int i = 0; i < datas.Length; i++)
      {
        this[datas[i]] = i;
      }
    }
    // 이것이 인덱서 문법이다.
    // 반환형과 함수명 자리에는 this를 넣고, 배열같이 대괄호로 데ㅇ이터를 받는다.
    public int this[string keyword]
    {
      // 인덱서의 get입니다.
      get
      {
        // 해당 키워드의 위치를 반환한다.
        for (int i = 0; i < data.Count; i++)
        {
          // 키워드와 맴버 변수 리스트의 객체 아이템과 같은 값이면
          if (string.Equals(data[i], keyword))
          {
            // 위치 반환
            return i;
          }
        }
        // 키워드가 없으면 -1를 반환
        return -1;
      }
      // 인덱서의 set입니다. (접근 제한자를 private로 설정함)
      private set
      {
        // 리스트에서 해당 키워드를 제거
        data.Remove(keyword);
        // 리스트에 index에 해당하는 위치에 키워드를 추가
        data.Insert(value, keyword);
      }
    }
    // 출력 함수
    public void Print()
    {
      // 맴버 변수 리스트 순서대로 
      foreach (var d in this.data)
      {
        // 콘솔 출력한다.
        Console.WriteLine(d);
      }
    }
  }
  class Program
  {
    // 실행 함수
    static void Main(string[] args)
    {
      // Node 인스턴스 생성
      Node node = new Node("Hello", "World");

      // 콘솔 출력
      node.Print();
      // World의 위치 출력
      Console.WriteLine(node["World"]);

      // 아무 키나 누르시면 종료합니다.
      Console.WriteLine("Press any key...");
      Console.ReadKey();
    }
  }
}

인덱서의 경우는 다른 언어의 문법에서는 없는 표현입니다. 그리고 배열과 매우 비슷한 문법을 지니고 있습니다.

이 인덱서가 잘 활용하면 소스도 많이 줄이고 괜찮은 방법으로 응용도 가능합니다만, 문제가 흔하지 않은 문법이다보니 가독성이 떨어집니다.

이 가독성이 떨어진다는 것은 C#을 잘 모르는 특히 Java가 주력인 개발자 분께서 C# 프로젝트를 참여하신다고 할때, 이런 인덱스 문법이 있으면 아무래도 헤갈리거나 이해가 되지 않을 수 있습니다.

그래서 그런지 실무에서는 그렇게 자주 사용되는 문법이지는 않습니다.


여기까지 C#에서 인덱서(Indexer)를 사용하는 방법에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.