C#프로그래밍 14 : 인덱서, foreach가 가능한 객체, 인터페이스

LeeWonjin·2022년 5월 10일
0

[학부]C#프로그래밍

목록 보기
14/21

인덱서

인덱스 []를 이용해 객체 내 데이터에 접근하게 해 주는 프로퍼티
즉, 인덱서를 사용하면 객체를 배열처럼 사용할 수 있음.
** 프로퍼티이지만 식별자는 없음

선언

this[]로 클래스 내에 선언한다.

class something{
  한정자 자료형 this[자료형 index]{
    get{
      return --something--
    }
    set {
      // set action.
    }
  }
}

아래는 bool의 배열 arr에 대해 인덱서를 구현한 것이다.

class Something
{
    private bool[] arr;
    public Something() { arr = new bool[5]; }

    internal bool this[int idx]
    {
        get { return arr[idx]; }
        set
        {
            if(idx >= arr.Length)
                Array.Resize<bool>(ref arr, idx + 1);
            arr[idx] = value;
        }
    }

    public int Length
    {
        get { return arr.Length; }
    }
}

class Program
{
    public static void Main(string[] args)
    {
        Something a = new Something();
        a[0] = true;
        a[4] = false;
        a[10] = true;
            
        for(int i=0; i<a.Length; i++)
        {
            Console.Write($"{a[i]} ");
            //True False False False False False False False False False True
        }
    }
}

foreach가 가능한 객체

IEnumerable 인터페이스를 상속한 객체는 foreach가 가능하다.
IEnumerable.GetEnumerator()메소드는 IEnumerator형식의 객체를 반환한다. 이는 상속받은 자식클래스에서 구현해야한다.

** 인터페이스를 상속한다
--> 그 인터페이스에 있는 메소드 원형들을 자식이 반드시 구현해야한다.

yield문으로 IEnumerable, IEnumerator 자동 상속

컴파일시 자동으로 IEnumerator를 상속하는 클래스 생성
즉, IEnumerator를 상속하는 대신 yield문을 이용 가능

class AA
{
    int[] nums = { 1, 2, 3, 4 };
    public IEnumerator GetEnumerator()
    {
        yield return nums[0];
        yield return nums[1];
        yield return nums[2];
        yield break;
        yield return nums[3];
    }
}

class Program
{
    static public void Main(string[] Args)
    {
        var a = new AA();
        foreach (int n in a)
        {
            Console.Write($"{n} "); // 1 2 3
        }
    }
}

IEnumerable, IEnumerator 직접 상속

IEnumerable을 상속하려면 아래 메소드를 정의해야 한다.

  • IEnumerator GetEnumerator()

IEnumerator를 상속하려면 아래 3개 메소드를 모두 정의해야 한다.

  • bool MoveNext()
  • void Reset()
  • object Current {get;}

만약 어떤 클래스가 MoveNext, Rest, Current를 모두 구현했다면, 이 클래스는 IEnumerator형으로 변환 가능하다.
즉, IEnumerator GetEnumerator()의 반환값은 this로 하면 된다.

class A : IEnumerable, IEnumerator
{
    private int[] arr;
    int pos = -1;
    public A() { arr = new int[3]; }

    public int this[int index]
    {
        get { return arr[index]; }
        set
        {
            if (index >= arr.Length)
                Array.Resize<int>(ref arr, index + 1);
            arr[index] = value;
        }
    }

    public object Current
    {
        get { return arr[pos]; }
    }

    public void Reset()
    {
        pos = -1;
    }

    public bool MoveNext()
    {
        if(pos == arr.Length - 1) // 순회 끝
        {
            Reset();
            return false;
        }
        pos++; // 계속 순회
        return (pos < arr.Length);
    }

    public IEnumerator GetEnumerator ()
    {
        return this;
    }
}

class Program
{
    static public void Main(string[] Args)
    {
        A a = new A();
        a[0] = 1;
        a[4] = 2;
        a[7] = 3;

        foreach(int n in a)
        {
            Console.Write($"{n} "); // 1 0 0 0 2 0 0 3
        }
    }
}
profile
노는게 제일 좋습니다.

0개의 댓글