본문 바로가기
프로그래밍/C#

C# 무명 메서드(Anonymous Method)

by bantomak 2023. 8. 2.

무명 메서드(Anonymous method)

C# 2.0에서부터 메서드를 미리 정의하지 않아도 되는 메서드명이 없는 무명 메서드(혹은 익명 메서드, Anonymous Method)를 지원하게 되었다. 만약 어떤 메서드가 일회용으로 단순한 문장들로 구성되어 있다면, 굳이 별도의 메서드를 정의하지 않아도 되는 것이다.

 

무명 메서드를 만들기 위해서는 delegate 키워드와 함께 아래와 같이 파라미터와 실행 문장 블록을 적으면 된다. delegate 뒤의 파라미터는 해당 메서드 원형(prototype)에 맞는 동일한 파라미터 타입이어야 하며, 실행 문장블록에는 여러 문장들을 쓸 수 있다. 무명 메서드는 외관상 인라인 메서드(inline method) 형식을 띠며, 무명 메서드 자체를 delegate 타입의 변수에 할당할 수도 있다.

 

// 무명메서드 형식: delegate(파라미터들) { 실행문장들 };
delegate(int param1) { Console.Write(param1); };

// 무명메서드를 delegate 타입 변수에 할당
delegate void MyDelegate(int a);

MyDelegate d = delegate(int p) 
{ 
   Console.Write(p); 
};

d(100);

 

무명 메서드 사용

C# 무명 메서드를 사용하기 위해서는 메서드가 필요한 곳에 직접 delegat로 시작하는 무명 메서드를 써주면 된다. 예를 들어, 무명 메서더를 델리게이트 변수에 할당해서 사용할수도 있고, 메서드의 파라미터에 인라인 형식으로 무명 메서드를 사용할 수도 있으며, 또한 이벤트 핸들러를 추가하는 곳에 무명메서드를 사용할 수 있다.

 

아래 예제는 이벤트 핸들러에 무명 메서드를 사용한 예이다. 예제에서 button1.Click 에는 미리 정의된 메서드명(button1_Click)을 가리키는 이벤트 핸들러를 지정하였고, button2.Click 에서는 무명 메서드를 사용하여 직접 간단한 문장을 인라인으로 delegate() {....} 안에 포함시킨 것이다.

 

public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();

      // 메서드명을 지정
      this.button1.Click += new System.EventHandler(this.button1_Click);

      // 무명메서드를 지정
      this.button2.Click += delegate(object s, EventArgs e)
      {
         MessageBox.Show("버튼2 클릭");
      };
   }

   private void button1_Click(object sender, EventArgs e)
   {
      MessageBox.Show("버튼1 클릭");
   }
}

 

델리게이트 타입 vs 무명 메서드

C#의 delegate 키워드는 델리게이트 타입을 정의할 때도 사용되고, 무명메서드를 정의할 때도 사용된다. 델리게이트 타입을 정의하는 아래 첫 번째 예의 경우, SumDelegate는 Delegate 클래스 타입명을 가리키게 되고, 클래스 객체를 생성할 때와 같이 new를 사용하여 Delegate 객체를 생성하고 이 객체에 특정 메서드를 연관시켜 할당하게 된다.

 

무명메서드는 이름이 없는 메서드 자체 만을 가리키는 것으로 그 자체로 Delegate 타입이 되는 것은 아니다. 따라서 아래 [무명메서드 1] 예제처럼 EventHandler 델리게이트 객체를 new로 생성하고 무명메서드를 파라미터로 전달하게 된다. 하지만 Event와 같이 이미 어떤 델리게이트 타입이 사용될지 아는 경우에는 (컴파일러가 Click 이벤트에는 new EventHandler(object, EventArgs) 형식의 이벤트 핸들러를 받아들인다는 것을 이미 알고 있다.) 아래 [무명메서드 2/3] 예제처럼 new EventHandler()나 (EventHandler) 캐스팅을 생략할 수 있다. 또한 마지막으로 만약 파라미터를 무명메서드 안에서 사용하지 않는다면, [무명메서드 4] 예제처럼 파라미터들을 완전히 생략할 수도 있다.

 

// Delegate 타입 : 
public delegate int SumDelegate(int a, int b);
                      
// Delegate 사용 : 
SumDelegate sumDel = new SumDelegate(mySum);
                      
// 무명메서드1 
button1.Click += new EventHandler(delegate(object s, EventArgs a) { MessageBox.Show("OK"); });

// 무명메서드2
button1.Click += (EventHandler) delegate(object s, EventArgs a) { MessageBox.Show("OK"); };

// 무명메서드3 
button1.Click += delegate(object s, EventArgs a) { MessageBox.Show("OK"); };

// 무명메서드4 
button1.Click += delegate { MessageBox.Show("OK"); };

 

델리게이트 타입을 사용해야 하는 곳에 무명메서드만 직접 사용하는 경우 컴파일 에러 (Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type)가 발생할 수 있다.

아래 예처럼, Control.Invoke() 혹은 Control.BeginInvoke() 메서드는 델리게이트 타입을 파라미터로 받아들인다. 즉 Invoke() 메서드는 파라미터로 받아들이는 Delegate의 파라미터가 몇개인지, 리턴 값은 무엇인지 미리 알지 못한다는 뜻이다. 따라서 무조건 무명메서드를 전달할 수 없고, 어떤 Delegate 타입인지를 명시적으로 지정해야 하고, 이런 조건이 충족되었을 때, Delegate 타입과 부합되는 무명메서드를 사용할 수 있다.

 

// 틀림: 컴파일 에러 발생
this.Invoke(delegate {button1.Text = s;} );

// 맞는 표현 
MethodInvoker mi = new MethodInvoker(delegate() { button1.Text = s; });
this.Invoke(mi);

// 축약된 표현
this.Invoke((MethodInvoker) delegate { button1.Text = s; });

/* 
MethodInvoker는 입력 파라미터가 없고, 리턴 타입이 void인 델리게이트이다.
MethodInvoker는 System.Windows.Forms 에 다음과 같이 정의되어 있다.

public delegate void MethodInvoker();
*/

 

이제 델리게이트 타입과 무명 메서드를 구분할 수 있어야 한다.

// delegate 타입
public delegate void MyDelegate(int a);

// 무명 메서드
delegate (int a) { Console.WriteLine(a); };

 

함께 읽으면 좋은 글

 

C# 람다(Lambda)에 대해서

람다의 형태 람다는 두가지 형태 중 하나의 형태를 가집니다. 람다식 (Lambda Expression) (parameters) => expression // 람다식으로 작성시 return 문을 생략할 수 있습니다. 람다문 (Lambda Statement) (parameters) => {

jettstream.tistory.com

출처

 

C# 무명 메서드 - C# 프로그래밍 배우기 (Learn C# Programming)

C# 무명 메서드 (Anonymous Method) 앞의 C# delegate 예제를 보면 예제의 delegate들은 모두 이미 정의된 메서드를 가리키고 있었다. 이렇게 미리 정의된 메서드들과는 달리, C# 2.0에서부터 메서드를 미리

www.csharpstudy.com

'프로그래밍 > C#' 카테고리의 다른 글

C# 인터페이스 이해하기  (8) 2023.08.03
C# Closure 이해하기  (22) 2023.08.02
C# 7.0 튜플(Tuple)  (6) 2023.07.27
C# Queue 기본 생성자로 초기화 하기  (18) 2023.07.26
C# virtual 키워드  (24) 2023.07.05

댓글