익명 메서드란 무엇인가?
익명 메서드(Anonymous Method)는 코드 블록 자체를 대리자(delegate)의 매개변수로 전달할 수 있게 해주는 기법입니다. 이름 그대로 메서드 이름 없이 본문(body)만으로 구성된 메서드를 의미하며, 별도의 명명된 메서드를 따로 정의하지 않고도 대리자에 간단한 로직을 바로 연결할 수 있다는 장점이 있습니다.
일회성으로 사용되는 짧은 코드나 이벤트 핸들러를 작성할 때 특히 유용하며, 코드의 가독성과 응집도를 높이는 데 도움이 됩니다.
C#에서 익명 메서드 선언하기
익명 메서드는 delegate 키워드를 사용해 선언합니다. 대리자 변수에 할당하는 시점에 메서드 본문을 직접 작성하는 형태입니다.
delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x) {
Console.WriteLine("Anonymous Method: {0}", x);
};
위 예시에서 nc라는 대리자 변수가 int 타입의 매개변수 하나를 받아 콘솔에 출력하는 익명 메서드를 참조하게 됩니다. 이후 nc(10);처럼 일반 메서드를 호출하듯 대리자를 호출하면 됩니다.
예제
다음은 C#에서 익명 메서드와 명명된 메서드(named method)를 함께 사용해 대리자를 구현한 전체 예제입니다.
using System;
delegate void NumberChanger(int n);
namespace DelegateAppl {
class Demo {
static int num = 10;
public static void AddNum(int p) {
num += p;
Console.WriteLine("Named Method: {0}", num);
}
public static void MultNum(int q) {
num *= q;
Console.WriteLine("Named Method: {0}", num);
}
public static int getNum() {
return num;
}
static void Main(string[] args) {
// 익명 메서드를 사용해 대리자 인스턴스 생성
NumberChanger nc = delegate(int x) {
Console.WriteLine("Anonymous Method: {0}", x);
};
// 익명 메서드로 대리자 호출
nc(10);
// 명명된 메서드로 대리자 인스턴스화
nc = new NumberChanger(AddNum);
// 명명된 메서드로 대리자 호출
nc(5);
// 다른 명명된 메서드로 대리자 재인스턴스화
nc = new NumberChanger(MultNum);
// 명명된 메서드로 대리자 호출
nc(2);
Console.ReadKey();
}
}
}
실행 결과
위 프로그램을 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
Anonymous Method: 10 Named Method: 15 Named Method: 30
출력 순서를 살펴보면, 먼저 익명 메서드가 매개변수 값 10을 그대로 출력하고, 이후 AddNum이 10 + 5 = 15를, 마지막으로 MultNum이 15 × 2 = 30을 출력하는 것을 확인할 수 있습니다. 하나의 대리자 변수가 참조하는 메서드를 교체해가며 호출하는 흐름을 잘 보여주는 예제입니다.
익명 메서드 사용 시 주의 사항
- 익명 메서드 내부에서는
break,goto,continue같은 점프 문을 사용해 익명 메서드 바깥으로 제어를 이동시킬 수 없습니다. - 반대로 익명 메서드 외부에서 내부로 점프하는 것도 허용되지 않습니다.
- 익명 메서드 내부에서는 외부 범위의
ref또는out매개변수에 접근할 수 없습니다. - 단, 외부 지역 변수나 필드에는 접근 가능하며, 이 경우 해당 변수는 클로저(closure)처럼 캡처됩니다.
람다 식과의 관계
C# 3.0부터 도입된 람다 식(lambda expression)은 익명 메서드를 더욱 간결하게 표현할 수 있는 문법으로, 실무에서는 익명 메서드보다 람다 식을 사용하는 것이 일반적입니다. 예를 들어 위의 익명 메서드는 다음과 같이 람다 식으로 대체할 수 있습니다.
NumberChanger nc = x => Console.WriteLine("Lambda Method: {0}", x);
다만 LINQ에서 식 트리(expression tree)로 변환되는 경우 등 일부 상황에서는 여전히 익명 메서드의 동작 방식을 이해하고 있는 것이 중요합니다.