[C#] 확장 메서드 : 기존 타입에 메서드 더하기

[C#] 확장 메서드 : 기존 타입에 메서드 더하기

안녕하세요. 이번 글에서는 C#의 확장 메서드(Extension Method)에 대해 알아보겠습니다.

string이나 List처럼 직접 수정할 수 없는 타입에 기능을 더하고 싶을 때, 상속을 하거나 별도의 도우미 클래스를 만들 수도 있습니다. 확장 메서드를 쓰면 기존 타입의 소스를 건드리지 않고도 마치 그 타입의 인스턴스 메서드인 것처럼 호출할 수 있습니다. LINQ의 Where, Select도 IEnumerable에 대한 확장 메서드입니다.

기본 사용법

확장 메서드는 static 클래스 안의 static 메서드이며, 첫 번째 매개변수 앞에 this 키워드를 붙여 확장할 타입을 지정합니다.

using System;

public static class StringExtensions
{
    // 지정한 길이를 넘으면 잘라내고 ...을 붙임
    public static string Truncate(this string s, int maxLength)
    {
        if (string.IsNullOrEmpty(s) || s.Length <= maxLength)
            return s;
        return s.Substring(0, maxLength) + "...";
    }

    public static int WordCount(this string s)
    {
        return s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

class Program
{
    static void Main()
    {
        string text = "Extension methods are convenient";

        Console.WriteLine(text.Truncate(9));    // Extension...
        Console.WriteLine(text.WordCount());    // 4

        // 일반 정적 메서드 호출과 동일
        Console.WriteLine(StringExtensions.WordCount(text));
    }
}

제네릭 타입에 확장하기

인터페이스나 제네릭 타입에도 확장 메서드를 만들 수 있습니다. IEnumerable<T>를 확장하면 배열, List 등 모든 컬렉션에서 쓸 수 있습니다.

using System;
using System.Collections.Generic;

public static class EnumerableExtensions
{
    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        foreach (var item in source)
            action(item);
    }
}

// 사용
var list = new List<int> { 1, 2, 3 };
list.ForEach(x => Console.WriteLine(x * 10));
new[] { "a", "b" }.ForEach(Console.WriteLine);

알아 둘 점

  • 확장 메서드가 있는 네임스페이스를 using해야 호출할 수 있습니다.
  • 타입에 같은 시그니처의 인스턴스 메서드가 있으면 인스턴스 메서드가 우선합니다. 확장 메서드는 가려집니다.
  • 실제로는 정적 메서드 호출이므로 null 인스턴스에서도 호출은 됩니다. 메서드 내부에서 null 검사가 필요합니다.
  • private·protected 멤버에는 접근할 수 없고 public 멤버만 사용할 수 있습니다.
  • 확장 메서드를 담는 클래스는 중첩이나 제네릭이 아닌 최상위 static 클래스여야 합니다.

참고

이상으로 C# 확장 메서드에 대해 간단히 알아보았습니다.