인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

조전욱님의 프로필 이미지

작성한 질문수

[유니티 레벨 업!] 모듈식으로 개발하는 퀘스트&업적 시스템

퀘스트 정보를 확인할 Quest View UI 제작

IEnumerable 에 대해 간략히 설명 가능할까요?

작성

·

4.5K

0

IEnumerator 은 아는데 IEnumerable  는 생소하네요. 구글 검색을 해봤는데 헷갈려서 강사님께 여쭤봅니다 ㅠ  

답변 1

1

Developer G님의 프로필 이미지
Developer G
지식공유자

수강해주셔서 감사합니다.

IEnumerable은 열거자라고 부르는 인터페이스로,

List<GameObject> gameObjects = new List<GameObject>();
foreach (var gameObject in gameObjects) <= 이것(foreach문)을 가능하게 해주는 것입니다.
     ...

IEnumerable을 구현함으로써 우리가 만드는 class들도 foreach문에 돌릴 수 있게 되는겁니다.
잘 설명한 구글 포스팅이 있어서(https://ansohxxn.github.io/c%20sharp/enumerate/) 이 포스팅에서 내용을 발췌하여 설명을 드리겠습니다.

 

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}


이런 사람(Person)을 정의을 하는 클래스가 있고,

public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];

        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }

// Implementation for the GetEnumerator method.
    IEnumerator IEnumerable.GetEnumerator()
    {
       return (IEnumerator) GetEnumerator();
    }

    public PeopleEnum GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

 

Person을 배열로 갖는 People이라는 클래스가 있다고 할 때,
우리가  foreach (var person in people)이라는 코드처럼 foreach문을 통해 Person 배열을 순회하고 싶다면, 이때 IEnumerable을 구현하게 됩니다.

IEnumerable을 통해 구현해야할 것은 위 People 클래스에 보이는

    IEnumerator IEnumerable.GetEnumerator()
    {
       return (IEnumerator) GetEnumerator();
    }

    public PeopleEnum GetEnumerator()
    {
        return new PeopleEnum(_people);
    }


이 두 가지인데요,
첫번 째 함수는 거진 고정된 내용이라고 보시면되는데, 두번 째 함수를 보면 PeopleEnum이라는 클래스가 보이실 겁니다. 이는 IEnumerable을 구현하기위해서는 IEnumerator도 상속받아 구현하여야 하는데, 하나의 클래스에서 IEnumerable과 IEnumerator를 모두 구현하게되면 클래스가 복잡해지기 때문에 PeopleEnum이라는 클래스를 새로 만들어서 복잡도를 나눈 것입니다.

public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    int position = -1; // 👉 _people 배열 인덱스로 활용할 것.

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

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

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public Person Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}


IEnumerator를 구현한 클래스의 모습인데요, 이 부분은 더 설명이 필요하지 않을 정도로 지금 보시는게 고정적인 형태라고 생각하시면 됩니다. 
이렇게 People에서 IEnumerable이, PeopleEnum에서 IEnumerator가 구현이되면 People 클래스의 Person 배열을 foreach를 통해서 순회할 수 있게 됩니다.
우리가 사용하는 foreach (var person in people)는 사실 다음과 비슷한 형태입니다.

IEnumerator enumerator = people.GetEnumerator();
while(enumerator.MoveNext())
    Console.WriteLine(Current.firstName + " " + Current.lastName);


보시는 것처럼 MoveNext를 통해 다음 배열 인덱스로 값이 증가하고 Current를 통해서 현재 배열값을 가져오는겁니다.
훨씬 자세한 내용은 위에 달아드린 링크에 있으니 꼭 한번 정독해보시길 추천드립니다.

감사합니다.

조전욱님의 프로필 이미지
조전욱
질문자

좀 어렵네요. 링크 보고 공부해볼게요. 감사합니다.