안녕하세요. 이번 글에서는 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# 확장 메서드에 대해 간단히 알아보았습니다.