c# IEnumerable 확장 메서드

2024. 9. 29. 20:20c#

IEnumerable 확장 메서드

C#에서 IEnumerable은 다양한 컬렉션을 반복(iteration)할 수 있도록 도와주는 기본 인터페이스입니다.
하지만 LINQ(Language Integrated Query) 덕분에 IEnumerable의 기능이 대폭 확장되었습니다.
LINQ 확장 메서드는 컬렉션을 더욱 효율적으로 다루고, 복잡한 작업을 간결한 코드로 해결할 수 있게 해줍니다.

이 글에서는 IEnumerable<T>에 대해 자주 사용되는 확장 메서드와 그 사용법에 대해 설명합니다.


1. 확장 메서드란?

확장 메서드는 기존 타입에 새로운 메서드를 추가하는 것처럼 보이게 하는 C#의 기능입니다.
실제로는 타입을 수정하는 것이 아니라, 새로운 메서드를 통해 그 타입에 기능을 추가하는 방식입니다.
이러한 확장 메서드는 static 클래스 내에서 정의되며, 첫 번째 매개변수에 this 키워드가 붙어 있습니다.

확장 메서드 정의 예시

public static class IEnumerableExtensions
{
    public static void PrintAll<T>(this IEnumerable<T> collection)
    {
        foreach (var item in collection)
        {
            Console.WriteLine(item);
        }
    }
}

위 코드는 IEnumerable<T> 타입에 PrintAll() 메서드를 추가하는 예시입니다.
이 메서드를 사용하면 컬렉션의 모든 요소를 출력할 수 있습니다.

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
numbers.PrintAll();

 


2. 자주 사용하는 LINQ 확장 메서드

LINQ는 여러 확장 메서드를 통해 IEnumerable을 더욱 강력하게 만들어줍니다.
LINQ 확장 메서드는 System.Linq 네임스페이스에 포함되어 있으며, 이를 사용하여 컬렉션을 필터링, 정렬, 변환, 집계할 수 있습니다.

2.1 Where

Where 메서드는 컬렉션의 요소 중 특정 조건을 만족하는 요소만 필터링하는 데 사용됩니다.

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
var evenNumbers = numbers.Where(n => n % 2 == 0);

foreach (var number in evenNumbers)
{
    Console.WriteLine(number);  // 2, 4, 6
}

2.2 Select

Select 메서드는 컬렉션의 요소를 변환하는 데 사용됩니다.
각 요소에 대해 변환 작업을 수행하고, 새로운 컬렉션을 반환합니다.

List<int> numbers = new List<int> { 1, 2, 3 };
var squares = numbers.Select(n => n * n);

foreach (var square in squares)
{
    Console.WriteLine(square);  // 1, 4, 9
}

2.3 OrderBy / OrderByDescending

OrderByOrderByDescending 메서드는 컬렉션을 정렬하는 데 사용됩니다.
OrderBy는 오름차순, OrderByDescending은 내림차순으로 정렬합니다.

List<string> names = new List<string> { "Charlie", "Alice", "Bob" };
var orderedNames = names.OrderBy(n => n);

foreach (var name in orderedNames)
{
    Console.WriteLine(name);  // Alice, Bob, Charlie
}

2.4 First / FirstOrDefault

First는 컬렉션의 첫 번째 요소를 반환하며, 조건을 지정할 수 있습니다.
조건을 만족하는 첫 번째 요소가 없으면 FirstOrDefault를 사용해 기본값을 반환할 수 있습니다.

List<int> numbers = new List<int> { 1, 2, 3 };
int firstNumber = numbers.First();              // 1
int firstEvenNumber = numbers.FirstOrDefault(n => n % 2 == 0);  // 2

2.5 Aggregate

Aggregate는 컬렉션의 모든 요소에 대해 누적 연산을 수행하는 메서드입니다.
예를 들어, 요소의 합이나 곱을 구할 때 사용할 수 있습니다.

List<int> numbers = new List<int> { 1, 2, 3, 4 };
int sum = numbers.Aggregate((acc, n) => acc + n);

Console.WriteLine(sum);  // 10

2.6 GroupBy

GroupBy는 컬렉션의 요소를 특정 키로 그룹화하는 메서드입니다.
그룹화를 통해 데이터의 구조를 쉽게 분석할 수 있습니다.

var people = new List<string> { "Alice", "Bob", "Charlie", "David" };
var groupedByFirstLetter = people.GroupBy(p => p[0]);

foreach (var group in groupedByFirstLetter)
{
    Console.WriteLine($"Key: {group.Key}");
    foreach (var person in group)
    {
        Console.WriteLine(person);  
    }
}

2.7 ToList / ToArray

ToListToArray는 IEnumerable<T>의 결과를 각각 List<T>T[] 배열로 변환하는 메서드입니다.

var numbers = new List<int> { 1, 2, 3 };
var numberArray = numbers.ToArray();
var numberList = numberArray.ToList();

3. 확장 메서드를 이용한 IEnumerable의 장점

IEnumerable<T> 확장 메서드를 사용하면 코드의 가독성이 향상되며, 더욱 선언적이고 간결한 방식으로 데이터를 처리할 수 있습니다. LINQ 확장 메서드는 컬렉션에 대해 필터링, 매핑, 집계와 같은 고급 작업을 단순화하여 유지 보수성과 성능을 향상시킵니다.


4. 사용자 정의 확장 메서드 예시

LINQ 외에도 자신만의 확장 메서드를 만들어 특정 작업을 처리할 수 있습니다.

예시: MinMax 확장 메서드

public static class IEnumerableExtensions
{
    public static (T Min, T Max) MinMax<T>(this IEnumerable<T> collection) where T : IComparable<T>
    {
        if (!collection.Any())
            throw new InvalidOperationException("컬렉션이 비어있습니다.");

        T min = collection.First();
        T max = collection.First();

        foreach (var item in collection)
        {
            if (item.CompareTo(min) < 0)
                min = item;
            if (item.CompareTo(max) > 0)
                max = item;
        }

        return (min, max);
    }
}

이 확장 메서드는 컬렉션의 최소값과 최대값을 동시에 반환합니다.

List<int> numbers = new List<int> { 3, 5, 1, 8, 2 };
var result = numbers.MinMax();

Console.WriteLine($"Min: {result.Min}, Max: {result.Max}");
// Min: 1, Max: 8

 


 

IEnumerable 확장 메서드를 사용하면 복잡한 컬렉션 처리 작업도 간단하게 수행할 수 있습니다.
LINQ 확장 메서드를 사용하여 데이터 필터링, 변환, 정렬, 그룹화 등 다양한 작업을 간편하게 처리할 수 있으며, 자신만의 확장 메서드를 만들어 특정 요구 사항에 맞춘 로직을 구현할 수도 있습니다.