Java의 함수형 인터페이스(Functional Interface)에 해당하는 C#의 개념은 바로 델리게이트(Delegate)입니다. 두 언어 모두 메서드를 변수처럼 다루고 람다 식과 함께 사용할 수 있다는 점에서 유사하지만, 구현 방식에는 차이가 있습니다.
Java에서의 함수형 인터페이스
Java에서 함수형 인터페이스는 추상 메서드를 정확히 하나만 가지는 인터페이스를 의미합니다. @FunctionalInterface 애노테이션을 붙이면 컴파일러가 이 조건을 검증해 주며, 람다 식이나 메서드 참조로 간결하게 구현할 수 있습니다.
예제 코드
@FunctionalInterface
public interface MyInterface {
void invoke();
}
public class Demo {
void method(){
MyInterface x = () -> MyFunc();
x.invoke();
}
void MyFunc() {
}
}위 예제에서 MyInterface는 단일 추상 메서드 invoke()를 가지므로 함수형 인터페이스로 동작하며, 람다 식 () -> MyFunc()를 통해 구현체를 생성하고 있습니다.
C#에서의 델리게이트
C#에는 별도의 함수형 인터페이스 문법이 없습니다. 대신 델리게이트(delegate) 타입이 그 역할을 수행합니다. 델리게이트는 메서드에 대한 참조를 저장할 수 있는 타입으로, Java의 함수형 인터페이스와 마찬가지로 람다 식을 할당할 수 있습니다.
예제 코드
public delegate void MyInterface();
public class Demo {
internal virtual void method() {
MyInterface x = () => MyFunc();
x();
}
internal virtual void MyFunc() {
}
}위 코드에서 delegate void MyInterface() 선언은 Java의 단일 메서드 인터페이스와 동일한 역할을 합니다. 람다 식을 델리게이트 변수에 할당한 후, x.invoke()처럼 메서드 이름을 붙여 호출하는 것이 아니라 x() 형태로 직접 호출한다는 점이 Java와의 주요 차이입니다.
두 방식의 비교
- 선언 방식: Java는 인터페이스를 직접 정의하는 반면, C#은
delegate키워드로 메서드 시그니처를 선언합니다. - 호출 방식: Java는 인터페이스의 메서드(
x.invoke())를 통해 호출하고, C#은 델리게이트 변수 자체를 함수처럼(x()) 호출합니다. - 표준 제공: C#은
Action,Func,Predicate같은 범용 델리게이트를 기본 제공하여 별도 선언 없이도 사용할 수 있습니다.
정리하자면, Java의 함수형 인터페이스가 람다 식을 수용하기 위한 타입 계약이라면, C#의 델리게이트는 메서드 참조 자체를 일급 시민(first-class citizen)으로 다루는 더 직접적인 방식이라고 할 수 있습니다.