방프리

21.04.15 Chapter4. LINQ 활용 (Item 31) 본문

C#/Effective C#

21.04.15 Chapter4. LINQ 활용 (Item 31)

방프리 2021. 4. 16. 00:02

Item 31 : 시퀸스에 사용할 수 있는 조합 가능한 API를 작성하라

 

이터레이터 메서드를 사용하면 재사용성이 올라가며 추가적인 저장소를 굳이 생성할 필요가 없다.

yield return을 통해 현재 위치를 계속 갱신하면서 출력 시퀸스에 차례대로 결과를 반환할 수 있다.

즉, 사용할 배열을 복사하는 것이 아닌 시퀸스 자체를 그대로 사용할 수 있다.

public static IEnumerable<int> Unique(IEnumerable<int> nums)
{
    var uniqueVals = new HashSet<int>();
    
    foreach(var num in nums)
    {
        if (!uniqueVals.Contains(num))
        {
            uniqueVals.Add(num);
            yield return num;
        }
    }
}

yield return처럼 현재 위치를 계속 갱신해가며 수행하는 메서드를 컨티뉴어블 메서드라고 한다.

컨티뉴어블 메서드는 두 가지 장점이 있는데,

첫 번째로 시퀸스 내의 개별 요소에 대해 지연 평가/수행이 가능하다.

두 번째로는 foreach 루프를 포함하고 있는 경우에도 조합 가능한 메서드로 만들 수 있다.

또한 제네릭으로도 표현이 가능하다.

public static IEnumerable<T> Unique(IEnumerable<T> nums)
{
    var uniqueVals = new HashSet<T>();
    
    foreach(T num in nums)
    {
        if (!uniqueVals.Contains(num))
        {
            uniqueVals.Add(num);
            yield return num;
        }
    }
}

해당 항목을 공부하면서 IEnumerator와 IEnumerable에 대해 좀 더 깊이 공부할 수 있었는데 IEnumerable은 List의 

하위호환이라고 생각하면 된다. 참고로 Collection도 이와 같이 비교대상이 되는데 List -> Collection -> IEnumerable

순서대로 상하관계로 생각하면 된다. 이쯤되면 각각을 언제 사용할 지 의문이 들기 시작하는데 StackOverflow에

잘 정리가 되어 있다.

IEnumerable, IEnumerable<T> : 읽기만 가능한 시퀸스에서 반복문을 사용할 때 

ICollection, ICollection<T> : 시퀸스를 수정하거나 크기에 신경써야할 때

IList, IList<T> : 시퀸스를 수정하거나 크기에 신경써야하며, 시퀸스의 요소의 위치나 순서를 수정해야할 때

List, List<T> : IList와 비슷한 경우

 

Comments