반응형

인덱서


인덱서는 프로퍼티( get{} set{} )를 확장한 형태와 유사합니다(거의 동일 this[..] 만 빼면)


인덱서는 배열 인덱싱 처럼 원소를 가져오거나 담을 수 있다는 뜻입니다


주로 멤버 배열 변수를 캡슐화 하기 위해 사용됩니다







인덱서는 클라이언트 응용 프로그램에서 배열과 마찬가지 방식으로 액세스할 수 있는 클래스구조체 또는 인터페이스를 만들 수 있게 해 주는 편리한 구문입니다. 인덱서는 주로 내부 컬렉션 또는 배열을 캡슐화하기 위한 형식에서 가장 많이 구현됩니다. 예를 들어 24시간 동안 10번 기록되는 온도를 화씨로 나타내는 TempRecord라는 클래스가 있다고 가정합니다. 클래스에는 온도를 나타내는 float 형식의 "temps"라는 배열과 온도를 기록한 날짜를 나타내는 DateTime이 들어 있습니다. 이 경우 인덱서를 구현하면 클라이언트는 float temp = tr.temps[4] 대신 float temp = tr[4]로 TempRecord 인스턴스의 온도에 액세스할 수 있습니다. 인덱서 표기법은 클라이언트 응용 프로그램의 구문을 단순하게 할 뿐 아니라 클래스와 해당 클래스의 용도를 다른 개발자가 쉽게 이해할 수 있도록 합니다.

클래스나 구조체에 대한 인덱서를 선언하려면 다음 예제에서와 같이 this 키워드를 사용합니다.

public int this[int index]    // Indexer declaration
{
    // get and set accessors
}




인덱서 형식과 해당 매개 변수 형식에는 적어도 인덱서 자체와 동등한 수준으로 액세스할 수 있어야 합니다. 액세스 가능성 수준에 대한 자세한 내용은 액세스 한정자를 참조하십시오.


인덱서 시그니처는 인덱서 정식 매개 변수의 수 및 형식으로 구성됩니다. 이 시그니처는 인덱서 형식 또는 정식 매개 변수 이름을 포함하지 않습니다. 같은 클래스에 두 개 이상의 인덱서를 선언한 경우, 모든 인덱서가 다른 시그니처를 가져야 합니다.

인덱서 값은 변수로 분류되지 않기 때문에 인덱서 값을 ref 또는 out 매개 변수로 전달할 수 없습니다.


예를 들어 다음과 같은 코드는 불가능 합니다

1
public float this[ref int index]
cs


위 코드는 다음과같은 에러를 발생시킵니다

오류 CS0631 이 컨텍스트에서는 ref 및 out을 사용할 수 없습니다.




다른 언어에서 사용할 수 있는 이름을 인덱서에 부여하려면 선언에 name 특성을 사용합니다. 예를 들면 다음과 같습니다.

[System.Runtime.CompilerServices.IndexerName("TheItem")]
public int this [int index]   // Indexer declaration
{
}

이 인덱서의 이름은 TheItem입니다. name 특성을 제공하지 않으면 기본 이름으로 Item이 사용됩니다.




인덱서 형식과 해당 매개 변수 형식에는 적어도 인덱서 자체와 동등한 수준으로 액세스할 수 있어야 합니다. 액세스 가능성 수준에 대한 자세한 내용은 액세스 한정자를 참조하십시오.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class TempRecord
{
    // Array of temperature values 
    private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
                                            61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
 
    // To enable client code to validate input  
    // when accessing your indexer. 
    public int Length
    {
        get { return temps.Length; }
    }
    // Indexer declaration. 
    // If index is out of range, the temps array will throw the exception. 
    public float this[int index]
    {
        get
        {
            return temps[index];
        }
 
        set
        {
            temps[index] = value;
        }
    }
}
 
class MainClass
{
    static void Main()
    {
        TempRecord tempRecord = new TempRecord();
        // Use the indexer's set accessor
        tempRecord[3= 58.3F;
        tempRecord[5= 60.1F;
 
 
        // Use the indexer's get accessor 
        for (int i = 0; i < 10; i++)
        {
            System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
        }
 
    }
}
/* Output:
        Element #0 = 56.2
        Element #1 = 56.7
        Element #2 = 56.5
        Element #3 = 58.3
        Element #4 = 58.8
        Element #5 = 60.1
        Element #6 = 65.9
        Element #7 = 62.1
        Element #8 = 59.2
        Element #9 = 57.5
    */
 

cs



C#에서는 인덱스 형식이 정수로만 제한되지 않습니다. 

예를 들어, 인덱서와 함께 문자열을 사용하는 것이 유용할 수 있습니다. 

이러한 인덱서는 컬렉션에서 문자열을 검색하고 적절한 값을 반환하여 구현할 수 있습니다. 

접근자로 오버로드할 수 있으므로 문자열과 정수 버전의 인덱스 형식은 함께 사용될 수 있습니다.




string 형태의 인덱서



이 예제에서는 요일을 저장하는 클래스를 선언합니다. 문자열과 요일 이름을 가져오고 상응하는 정수를 반환하는 get 접근자를 선언합니다. 

예를 들어, 일요일은 0을 반환하고 월요일은 1을 반환하는 방식입니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Using a string as an indexer value 
class DayCollection
{
    string[] days = { "Sun""Mon""Tues""Wed""Thurs""Fri""Sat" };
 
    // This method finds the day or returns -1 
    private int GetDay(string testDay)
    {
  //보다 효율적인 방법은 아니지만 예제를 위해서..
        for (int j = 0; j < days.Length; j++)
        {
            if (days[j] == testDay)
            {
                return j;
            }
        }
 // \" " 를 표현하기 위한 역슬래쉬
        throw new System.ArgumentOutOfRangeException(testDay, "testDay must be in the form \"Sun\", \"Mon\", etc");
    }
 
    // The get accessor returns an integer for a given string 
    public int this[string day]
    {
        get
        {
            return (GetDay(day));
        }
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        DayCollection week = new DayCollection();
        System.Console.WriteLine(week["Fri"]);
 
        // Raises ArgumentOutOfRangeException
        System.Console.WriteLine(week["Made-up Day"]);
 
        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}
// Output: 5

cs







인터페이스 인덱서


interface(C# 참조) 에서 인덱서를 선언할 수 있습니다. 인터페이스 인덱서의 접근자와 클래스 인덱서의 접근자는 다음과 같은 차이점이 있습니다.

  • 인터페이스 접근자는 한정자를 사용하지 않습니다.

  • 인터페이스 접근자에는 본문이 없습니다.

따라서 접근자의 목적은 인덱서가 읽기/쓰기, 읽기 전용 또는 쓰기 전용인지 여부를 나타내는 것입니다.

다음은 인터페이스 인덱서 접근자의 예제입니다.


public interface ISomeInterface
{
    //... 

    // Indexer declaration: 
    string this[int index]
    {
        get;
        set;
    }
}




인터페이스 인덱서 구현 예


다음 예제는 인터페이스 인덱서의 구현 방법을 보여 줍니다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Indexer on an interface: 
    public interface ISomeInterface
    {
        // Indexer declaration: 
        int this[int index]
        {
            get;
            set;
        }
    }
 
    // Implementing the interface. 
    class IndexerClass : ISomeInterface
    {
        private int[] arr = new int[100];
        public int this[int index]   // indexer declaration
        {
            get
            {
                // 배열 범위 밖의 index 가 올 경우 크래쉬
                return arr[index];
            }
            set
            {
                arr[index] = value;
            }
        }
    }
 
    class MainClass
    {
        static void Main()
        {
            IndexerClass test = new IndexerClass();
            System.Random rand = new System.Random();
            // Call the indexer to initialize its elements. 
            for (int i = 0; i < 10; i++)
            {
                test[i] = rand.Next(); //랜던값 얻기
            }
            for (int i = 0; i < 10; i++)
            {
                System.Console.WriteLine("Element #{0} = {1}", i, test[i]);
            }
 
        }
    }
    /* Sample output:
        Element #0 = 360877544
        Element #1 = 327058047
        Element #2 = 1913480832
        Element #3 = 1519039937
        Element #4 = 601472233
        Element #5 = 323352310
        Element #6 = 1422639981
        Element #7 = 1797892494
        Element #8 = 875761049
        Element #9 = 393083859
     */

cs









ref : https://msdn.microsoft.com/ko-kr/library/2549tw02(v=vs.120).aspx

ref : https://msdn.microsoft.com/ko-kr/library/tkyhsw31(v=vs.120).aspx




반응형

+ Recent posts