인덱서 (프로그래밍)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

인덱서는 C#에서 `operator[]`를 사용하여 구현되며, 클래스나 구조체에서 배열과 유사하게 특정 값을 가져오거나 설정할 수 있도록 해주는 기능이다. 프로퍼티와 유사하지만, 매개변수를 받는다는 점이 다르다. C#에서는 `this[첨자 목록]` 형식으로 선언하며, get 및 set 접근자를 통해 값을 읽고 쓸 수 있다. 다른 언어와의 상호 운용을 위해 기본적으로 `Item`이라는 이름의 인덱스 속성이 자동으로 생성되며, `System.Runtime.CompilerServices.IndexerNameAttribute` 속성을 사용하여 이름을 명시적으로 지정할 수 있다. Visual Basic에서는 `Default` 키워드를 사용하여 인덱서를 정의한다.

인덱서 (프로그래밍)
프로그래밍
종류언어 기능
언어C 샤프
사용 목적클래스의 인스턴스를 배열처럼 접근하기 위한 구문
유사 개념연산자 오버로딩
📚 더 읽어볼만한 페이지
  • 연산자 (프로그래밍) - 중위 표기법
    중위 표기법은 사람이 이해하기 쉬운 연산자 표기 방식이지만, 컴퓨터가 구문 분석하기 어렵고 연산 순서를 위해 괄호나 연산자 우선순위 규칙이 필요하다.
  • 연산자 (프로그래밍) - 형 변환
    형 변환은 프로그래밍에서 변수의 데이터 타입을 변경하는 것으로, 암시적 형 변환과 명시적 형 변환으로 나뉘며, 객체 지향 프로그래밍에서는 업캐스팅과 다운캐스팅이 발생하고, 각 언어는 고유한 규칙과 방법을 제공하며 잘못된 형 변환은 오류를 유발할 수 있다.
  • 프로그래밍 언어 주제 - 프로그래밍 패러다임
    프로그래밍 패러다임은 프로그래머에게 프로그램 작성 방식을 제시하는 관점 또는 스타일이며, 구조적 프로그래밍을 시작으로 절차적, 객체 지향, 선언형 등으로 발전해 명령형, 선언형, 멀티 패러다임 프로그래밍 언어로 분류된다.
  • 프로그래밍 언어 주제 - 프로그램 최적화
    프로그램 최적화는 컴퓨터 프로그램의 효율성을 높이는 과정으로, 더 효율적인 구현 방식을 선택하거나 불필요한 기능을 제거하여 문제 해결에 집중하며, 다양한 수준에서 플랫폼 의존적이거나 독립적인 기술을 활용하여 수행되지만, 특정한 품질 지표를 개선하기 위해 다른 측면을 희생하는 트레이드오프가 발생할 수 있다.
  • 객체 지향 프로그래밍 - Is-a
    Is-a 관계는 객체 지향 프로그래밍에서 한 유형이 다른 유형의 하위 유형임을 나타내는 관계로, 상속, 서브타이핑, 리스코프 치환 원칙과 관련되며, C++, Python, Java 등에서 표현된다.
  • 객체 지향 프로그래밍 - 객체 (컴퓨터 과학)
    객체는 객체 지향 프로그래밍에서 데이터와 조작을 묶어 메시지를 수신하고, 프로그램의 개념을 표현하며 가시성과 재사용성을 높이는 실체이다.

2. 구현

인덱서는 C#에서 `operator[]`에 대한 get 및 set 접근자를 통해 구현된다. 이는 프로퍼티와 유사하지만, 정적이 아니며 인덱서의 접근자가 매개변수를 받는다는 점에서 차이가 있다. get 및 set 접근자는 인덱서 선언의 매개변수 목록을 사용하여 메서드로 호출되지만, set 접근자는 여전히 암시적 `value` 매개변수를 갖는다.

3. 예제

C#에서는 클래스 및 구조체 내부에 인덱서를 가질 수 있다.

인덱서는 `this[첨자 목록]` 형식으로 선언한다.

인덱서의 구문 내에서는 `get`/`set`이, `set` 접근자 내에서는 `value`가 각각 문맥 키워드로 기능한다.

```csharp
class Matrix2x2 {
private readonly int[][] items = new[]{
new[] { 0, 0 },
new[] { 0, 0 },
};

// 셀의 값을 가져오고 설정하는 인덱서.
public int this[int index0, int index1] {
get { return items[index0][index1]; }
set { items[index0][index1] = value; }
}
}
```

호출 측에서는 배열에 접근하는 것과 같은 구문으로 인덱서의 기능을 호출한다.

```csharp
var matrix = new Matrix2x2();
// set 접근
matrix[0, 0] = 10;
// get 접근
int num = matrix[0, 1];
// get ⇒ 가산 ⇒ set
matrix[1, 0] += 10;
```

일반적인 메서드와 달리, 대입을 수반하지 않는 인덱서 메서드의 호출은 수행할 수 없다. 아래와 같은 호출은 구문 오류가 되며, 반환 값 void형의 인덱서를 정의하는 것도 불가능하다. 단, 인덱서를 통해 호출한 객체의 멤버를 호출하는 경우에는 구문상 문제가 없다.

```csharp
// 구문 오류로 처리된다.
matrix[1, 0];

// 다음 호출은 문제가 없다 (이 예에서는 의미가 없는 호출이지만)
matrix[1, 0].ToString();
```
C#에서 인덱서를 클래스에 사용한 예는 다음과 같다.

```csharp
class OurFamily
{
private long[] familyMember = new long[7];
public long this [int index]
{
// The get accessor
get
{
return familyMember[index];
}

// The set accessor with
set
{
familyMember[index] = value;
}
}
}
```

다음은 클래스에서 인덱서를 사용하는 C# 예제이다.

```csharp
class Family
{
private List _familyMembers = new List();

public Family(params string[] members)
{
_familyMembers.AddRange(members);
}

public string this[int index]
{
// The get accessor
get => _familyMembers[index];

// The set accessor with
set => _familyMembers[index] = value;
}

public int this[string val]
{
// Getting index by value (first element found)
get => _familyMembers.FindIndex(m => m == val);
}

public int Length => _familyMembers.Count;
}
```

사용 예시:

```csharp
void Main()
{
var doeFamily = new Family("John", "Jane");
for (int i = 0; i < doeFamily.Length; i++)
{
var member = doeFamily[i];
var index = doeFamily[member]; // same as i in this case, but it demonstrates indexer overloading allowing to search doeFamily by value.
Console.WriteLine($"{member} is the member number {index} of the {nameof(doeFamily)}");
}
}
```

이 예제에서 인덱서는 n번째 위치의 값을 가져오고, 해당 값으로 참조되는 목록의 위치를 가져오는 데 사용된다.

코드의 출력은 다음과 같다.


John is the member number 0 of the doeFamily
Jane is the member number 1 of the doeFamily

3.1. C#

C#에서는 클래스 및 구조체 내부에 인덱서를 가질 수 있다.

인덱서는 `this[첨자 목록]` 형식으로 선언한다.

인덱서의 구문 내에서는 `get`/`set`이, `set` 접근자 내에서는 `value`가 각각 문맥 키워드로 기능한다.

```csharp
class Matrix2x2 {
private readonly int[][] items = new[]{
new[] { 0, 0 },
new[] { 0, 0 },
};

// 셀의 값을 가져오고 설정하는 인덱서.
public int this[int index0, int index1] {
get { return items[index0][index1]; }
set { items[index0][index1] = value; }
}
}
```

호출 측에서는 배열에 접근하는 것과 같은 구문으로 인덱서의 기능을 호출한다.

```csharp
var matrix = new Matrix2x2();
// set 접근
matrix[0, 0] = 10;
// get 접근
int num = matrix[0, 1];
// get ⇒ 가산 ⇒ set
matrix[1, 0] += 10;
```

일반적인 메서드와 달리, 대입을 수반하지 않는 인덱서 메서드의 호출은 수행할 수 없다. 아래와 같은 호출은 구문 오류가 되며, 반환 값 void형의 인덱서를 정의하는 것도 불가능하다. 단, 인덱서를 통해 호출한 객체의 멤버를 호출하는 경우에는 구문상 문제가 없다.

```csharp
// 구문 오류로 처리된다.
matrix[1, 0];

// 다음 호출은 문제가 없다 (이 예에서는 의미가 없는 호출이지만)
matrix[1, 0].ToString();
```
C#에서 인덱서를 클래스에 사용한 예는 다음과 같다.

```csharp
class OurFamily
{
private long[] familyMember = new long[7];
public long this [int index]
{
// The get accessor
get
{
return familyMember[index];
}

// The set accessor with
set
{
familyMember[index] = value;
}
}
}
```

다음은 클래스에서 인덱서를 사용하는 C# 예제이다.

```csharp
class Family
{
private List _familyMembers = new List();

public Family(params string[] members)
{
_familyMembers.AddRange(members);
}

public string this[int index]
{
// The get accessor
get => _familyMembers[index];

// The set accessor with
set => _familyMembers[index] = value;
}

public int this[string val]
{
// Getting index by value (first element found)
get => _familyMembers.FindIndex(m => m == val);
}

public int Length => _familyMembers.Count;
}
```

사용 예시:

```csharp
void Main()
{
var doeFamily = new Family("John", "Jane");
for (int i = 0; i < doeFamily.Length; i++)
{
var member = doeFamily[i];
var index = doeFamily[member]; // same as i in this case, but it demonstrates indexer overloading allowing to search doeFamily by value.
Console.WriteLine($"{member} is the member number {index} of the {nameof(doeFamily)}");
}
}
```

이 예제에서 인덱서는 n번째 위치의 값을 가져오고, 해당 값으로 참조되는 목록의 위치를 가져오는 데 사용된다.

코드의 출력은 다음과 같다.


John is the member number 0 of the doeFamily
Jane is the member number 1 of the doeFamily

3.1.1. C# 코드 예제

wikitext
C#에서 인덱서를 클래스에 사용한 예는 다음과 같다.

```csharp
class OurFamily
{
private long[] familyMember = new long[7];
public long this [int index]
{
// The get accessor
get
{
return familyMember[index];
}

// The set accessor with
set
{
familyMember[index] = value;
}
}
}
```

다음은 클래스에서 인덱서를 사용하는 C# 예제이다.

```csharp
class Family
{
private List _familyMembers = new List();

public Family(params string[] members)
{
_familyMembers.AddRange(members);
}

public string this[int index]
{
// The get accessor
get => _familyMembers[index];

// The set accessor with
set => _familyMembers[index] = value;
}

public int this[string val]
{
// Getting index by value (first element found)
get => _familyMembers.FindIndex(m => m == val);
}

public int Length => _familyMembers.Count;
}
```

사용 예시:

```csharp
void Main()
{
var doeFamily = new Family("John", "Jane");
for (int i = 0; i < doeFamily.Length; i++)
{
var member = doeFamily[i];
var index = doeFamily[member]; // same as i in this case, but it demonstrates indexer overloading allowing to search doeFamily by value.
Console.WriteLine($"{member} is the member number {index} of the {nameof(doeFamily)}");
}
}
```

이 예제에서 인덱서는 n번째 위치의 값을 가져오고, 해당 값으로 참조되는 목록의 위치를 가져오는 데 사용된다.

코드의 출력은 다음과 같다.


John is the member number 0 of the doeFamily
Jane is the member number 1 of the doeFamily

3.1.2. 다른 언어와의 상호 운용

다른 언어와의 상호 운용을 위해 기본적으로 `Item`이라는 이름의 인덱스 속성이 자동으로 생성된다.

`System.Runtime.CompilerServices.IndexerNameAttribute` 속성을 추가하여 자동으로 생성되는 인덱서의 이름을 명시적으로 지정할 수 있다. 이 기능이 활용되는 대표적인 예시로 System.String 클래스를 들 수 있다. `System.String` 클래스에서는 인덱서의 이름이 `Chars`가 되도록 지정되어 있다.

3.2. Visual Basic (.NET)

Visual Basic에서는 `Default` 키워드가 붙은 인덱싱된 프로퍼티를 인덱서로 접근할 수 있다.

```vbnet
Public Class StringArray
Private m_Item As String() = New String(10) {}
' Default가 선언된 인덱싱된 프로퍼티는 인덱서로 접근 가능
Default Public Property Item(index As Integer) As String
Get
Return m_Item(index)
End Get
Set(ByVal value As String)
m_Item(index) = value
End Set
End Property
End Class
```

```vbnet
Dim obj As StringArray = New StringArray
' get 접근
Dim str As String = obj(1)
' set 접근
obj(2) = str

4. 추가 설명 (일본어 문서 내용)