0Pricing
C# Academy · 강의

인터페이스와 제네릭 확장

한 번에 여러 형식에 동작을 추가합니다.

인터페이스와 제네릭 확장은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

인터페이스 확장하기

this 매개변수가 인터페이스인 확장 메서드를 작성할 수 있습니다. 해당 인터페이스를 구현하는 모든 형식이 즉시 이 메서드를 사용할 수 있게 됩니다. LINQ가 IEnumerable<T>에 수십 개의 메서드를 추가하는 방식이 바로 이것입니다.

IEnumerable을 확장하는 제네릭 메서드

메서드를 T에 대해 제네릭으로 만들고 IEnumerable<T>를 확장하면 이 도우미를 목록, 배열, 쿼리 결과 등 모든 순서열에서 사용할 수 있습니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static bool IsEmpty<T>(this IEnumerable<T> source)
    {
        foreach (var item in source) return false;
        return true;
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 1, 2, 3 };
        Console.WriteLine(nums.IsEmpty());
        Console.WriteLine(new int[0].IsEmpty());
    }
}

시퀀스 순회

확장 메서드 내부에서는 매개 변수를 일반적인 IEnumerable<T>처럼 다룹니다. 여기서는 LINQ에 의존하지 않고 합계를 계산합니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static int SumValues(this IEnumerable<int> source)
    {
        int total = 0;
        foreach (var n in source) total += n;
        return total;
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 10, 20, 30 };
        Console.WriteLine(nums.SumValues());
    }
}

새 시퀀스 반환

확장 메서드는 시퀀스를 반환할 수도 있습니다. yield return과 함께 사용하면 지연 방식으로 동작하는 LINQ 스타일 연산자가 됩니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
    {
        bool take = true;
        foreach (var item in source)
        {
            if (take) yield return item;
            take = !take;
        }
    }
}

public class Program
{
    public static void Main()
    {
        var letters = new List<string> { "a", "b", "c", "d", "e" };
        foreach (var l in letters.EveryOther())
            Console.WriteLine(l);
    }
}

제네릭 형식 제약 조건

제네릭 매개 변수에 필요한 기능을 갖추도록 제약 조건을 지정할 수 있습니다. 여기서 where T : IComparable<T>를 사용하면 항목을 비교하여 최댓값을 찾을 수 있습니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static T MaxItem<T>(this IEnumerable<T> source) where T : IComparable<T>
    {
        bool started = false;
        T best = default;
        foreach (var item in source)
        {
            if (!started || item.CompareTo(best) > 0) { best = item; started = true; }
        }
        return best;
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 3, 9, 1, 7 };
        Console.WriteLine(nums.MaxItem());
    }
}

사용자 지정 인터페이스 확장

직접 만든 인터페이스도 확장할 수 있습니다. 인터페이스를 정의한 다음, 모든 구현 형식에 동작을 중복해서 작성하는 대신 확장 메서드로 공통 동작을 연결합니다.

using System;

public interface INamed { string Name { get; } }

public class Dog : INamed { public string Name => "Rex"; }

public static class NamedExtensions
{
    public static string Greeting(this INamed n) => "Hello, " + n.Name;
}

public class Program
{
    public static void Main()
    {
        var d = new Dog();
        Console.WriteLine(d.Greeting());
    }
}

여러 형식 매개 변수

확장 메서드는 여러 형식 매개 변수에 대해 제네릭으로 작성할 수 있습니다. 이 프로젝션 도우미는 함수로 시퀀스를 매핑하며, LINQ의 Select와 비슷하게 동작합니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static IEnumerable<TResult> Map<TSource, TResult>(
        this IEnumerable<TSource> source, Func<TSource, TResult> f)
    {
        foreach (var item in source) yield return f(item);
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 1, 2, 3 };
        foreach (var s in nums.Map(n => "#" + n))
            Console.WriteLine(s);
    }
}

기본 제공 LINQ와 결합

사용자 지정 확장 메서드는 LINQ와 함께 사용할 수 있습니다. 하나의 유창한 파이프라인에서 사용자 지정 연산자를 표준 연산자와 연결할 수 있습니다.

using System;
using System.Collections.Generic;
using System.Linq;

public static class EnumerableExtensions
{
    public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
    {
        bool take = true;
        foreach (var item in source) { if (take) yield return item; take = !take; }
    }
}

public class Program
{
    public static void Main()
    {
        var nums = Enumerable.Range(1, 10);
        var result = nums.Where(n => n > 2).EveryOther().ToList();
        Console.WriteLine(string.Join(", ", result));
    }
}

IEnumerable 확장으로 다양한 형식 지원

배열, 목록, 사전, 해시 집합, 쿼리 결과는 모두 IEnumerable<T>를 구현하므로 하나의 확장 메서드로 이 모든 형식을 한 번에 처리할 수 있습니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static int CountItems<T>(this IEnumerable<T> source)
    {
        int n = 0;
        foreach (var item in source) n++;
        return n;
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(new[] { 1, 2, 3 }.CountItems());
        Console.WriteLine(new HashSet<string> { "a", "b" }.CountItems());
    }
}

이 패턴이 확장되는 이유

인터페이스 확장을 사용하면 상속 없이 다형적인 도우미를 만들 수 있습니다. 인터페이스를 기준으로 로직을 한 번만 작성하면 현재와 앞으로 추가될 모든 구현 형식에서 이를 그대로 사용할 수 있습니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static string JoinWith<T>(this IEnumerable<T> source, string sep)
    {
        return string.Join(sep, source);
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 1, 2, 3 };
        Console.WriteLine(nums.JoinWith(" -> "));
    }
}

직접 해 보기

IEnumerable<T>를 대상으로 작은 제네릭 연산자를 만들고 LINQ와 연결해 보십시오. 어떤 시퀀스 형식에서도 작동하는지 확인해 보십시오.

using System;
using System.Collections.Generic;
using System.Linq;

public static class EnumerableExtensions
{
    public static IEnumerable<T> WithoutDuplicatesByKey<T, TKey>(
        this IEnumerable<T> source, Func<T, TKey> keySelector)
    {
        var seen = new HashSet<TKey>();
        foreach (var item in source)
            if (seen.Add(keySelector(item))) yield return item;
    }
}

public class Program
{
    public static void Main()
    {
        var words = new[] { "apple", "avocado", "banana", "cherry", "blueberry" };
        var firstPerLetter = words.WithoutDuplicatesByKey(w => w[0]);
        Console.WriteLine(string.Join(", ", firstPerLetter));
    }
}

빠른 확인

LINQ 스타일 확장 메서드를 어떻게 선언하는지 생각해 보십시오.

요약

인터페이스, 특히 IEnumerable<T>를 확장하는 것은 LINQ 스타일 프로그래밍의 기반입니다.

  • 메서드를 제네릭으로 만들고 인터페이스를 this 형식으로 사용합니다.
  • yield return을 사용하여 지연 방식으로 동작하는 연산자를 만듭니다.
  • where 제약 조건을 적용하여 IComparable<T>와 같은 기능을 요구합니다.
  • 하나의 인터페이스 확장으로 앞으로 추가될 형식을 포함한 모든 구현 형식을 처리할 수 있습니다.

자주 묻는 질문

“인터페이스와 제네릭 확장” 강의는 무료인가요?

네 — “인터페이스와 제네릭 확장” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“인터페이스와 제네릭 확장”에서 뭘 배우나요?

한 번에 여러 형식에 동작을 추가합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C# Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“인터페이스와 제네릭 확장” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 확장 메서드 정의
  2. 인터페이스와 제네릭 확장
  3. 확장 메서드 확인 과정
  4. 좋은 확장 기능 설계
← C# Academy(으)로 돌아가기