델리게이트 (delegate) - 2 / Delegate Chain / 이벤트

강성원·2024년 1월 17일
0

C# 끄적끄적

목록 보기
11/11
public class MyClass
{
	public delegate void Mydel(string message);
    public Mydel mydel;
}

static void WriteMessage1(string message)
{ Console.WriteLine("1 : "+message); }

static void WriteMessage2(string message)
{ Console.WriteLine("2 : "+message); }

아래의 글은 클래스 MyClass와 델리게이트 Mydel, 그리고 일반 메서드 2가지가 있다고 가정한다.

Multicast Delegate

System.MulticastDelegateSystem.Delegate 클래스를 상속받은 것으로, 여러 메서드를 할당하고 순서대로 호출할 수 있다.

"+", "+=" 연산자 사용

"+"연산자 혹은 "+="연산자를 사용하면 델리게이트에 메서드를 계속 추가할 수 있다.

연산자가 내부적으로 알아서 처리하기 때문에 메서드 이름만 넣어줘도 되고,
new 키워드를 사용해도 된다.

public class Program
{
    void Main(string[] args)
    {
        MyClass myClass = new MyClass();

        myClass.mydel += WriteMessage1;
        myClass.mydel += WriteMessage2;
        // myClass.mydel += new Mydel(WriteMessage2);

        myClass.mydel("메서드들 출력")
        // "1 : 메서드들 출력"
        // "2 : 메서드들 출력"
    }
}

MulticastDelegate를 상속받은 델리게이트는 추가된 메서드들의 리스트인InvocationList라는 속성을 가지고 있다.

여러 메서드가 할당된 델리게이트가 사용될 때 InvocationList속성을 통해서 메서드들에 접근할 수 있고 순서대로 메서드를 가져와 호출한다.

Delegate[] invocationList = myClass.mydel.GetInvocationList();

GetInvocationList()메서드로 델리게이트 내부에 할당된 메서드의 리스트를 가져올 수도 있다.


Delegate Chain

Delegate ChainMulticastDelegate과 밀접한 관련이 있다.
여러 델리게이트를 하나로 묶어 하나의 멀티 캐스트 델리게이트로 만드는 것을 Delegate Chain 이라고 한다.

Delegate.Combine 사용

public class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();


        myClass.mydel = (Mydel)Delegate.Combine(
            new Mydel(WriteMessage1),
            new Mydel(WriteMessage2)
            );

        myClass.mydel("출력");
    }
}

이런 식으로 Delegate.Combine 메서드로 여러 델리게이트를 묶어서 하나의 멀티 캐스트 델리게이트로 만들어줄 수 있다.


이벤트

이벤트는 델리게이트를 기반으로 하는 특별한 멤버이다.
델리게이트를 좀 더 안정적으로 사용할 수 있도록 도와준다.

이벤트는 멀티 캐스트 델리게이트에 메서드를 추가하는 것과 비슷하지만 몇 가지가 다르다.

  1. "=" 연산자를 사용하여 메서드를 추가할 수 없는 점.
    "+=", "-="연산자만 사용가능하다.

  2. 직접 클래스 외부에서 이벤트에 접근해서 메서드를 전달하고 호출할 수는 없는 점.
    이 부분은 밑에서 더 자세하게..

이벤트 선언

먼저 선언한 델리게이트와 event 키워드를 사용해서 하나의 이벤트 멤버를 선언할 수 있다.

public class MyClass
{
    public delegate void Mydel(string message);
    public Mydel mydel;

    public event Mydel MyEvent; 	// 이벤트 선언
}

이벤트 등록 / 해제 (메서드 할당)

무조건 "+=", "-="연산자만 사용해서 이벤트에 메서드를 등록, 해제할 수 있다.

public class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();

        myClass.MyEvent += WriteMessage1;
        myClass.MyEvent += WriteMessage2;

        myClass.MyEvent -= WriteMessage2;
    }
}

이 부분은 멀티 캐스트 델리게이트가 여러 메서드를 담고 있을 때
"=" 연산자 하나로 전에 담은 메서드가 전부 날라가버리는 일을 막기 위한 것으로 보인다.

이벤트 발생

차이점에서 언급한 부분이다.
이벤트의 호출은 클래스 내부에서 다른 메서드를 통해서 이루어져야한다.
말이 더 어려우니 코드를 보자.

public class MyClass
{
    public delegate void Mydel(string message);
    public Mydel mydel;

    public event Mydel MyEvent;

    public void ShowSomething(String str)
    {
        if (MyEvent != null)
            MyEvent(str);
    }
}

public class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();

        myClass.MyEvent += WriteMessage1;
        myClass.MyEvent += WriteMessage2;

        // myClass.MyEvent(str); => 직접 접근해서 이벤트 발생은 불가

        myClass.ShowSomething("출력");
    }
}

MyClass클래스에 ShowSomething() 메서드를 선언하는데, 그 안에서 이벤트 MyEvent를 호출한다.

Main에 중간에 써놓았듯이 외부에서 직접 인자를 넣어서 이벤트를 호출할 수 는 없도록 막혀있다.


분류하지 않은 정보

나 :
그냥 멀티 캐스트 델리게이트에 메서드를 추가하는 것과
여러 델리게이트를 Delegate.Combine을 이용해서 하나의 멀티 캐스트 델리게이트로 만드는 것은 비슷하지만 다른 것이라고 할 수 있겠네?

ChatGPT :
맞습니다. 멀티캐스트 델리게이트에 메서드를 직접 추가하는 것과 Delegate.Combine을 사용하여 여러 델리게이트를 결합하여 멀티캐스트 델리게이트를 생성하는 것은 약간의 차이가 있습니다.

  • 멀티 캐스트 델리게이트에 메서드 직접 추가
MyDelegate multiDelegate = Method1;
multiDelegate += Method2;
multiDelegate += Method3;
  • 델리게이트 체인
MyDelegate multiDelegate = (MyDelegate)Delegate.Combine(new MyDelegate(Method1), new MyDelegate(Method2), new MyDelegate(Method3));

두 방법은 결국 같은 결과를 얻지만, 두 번째 방법은 더 일반적이고 동적인 상황에 유용합니다. Delegate.Combine을 사용하면 여러 델리게이트를 동적으로 결합할 수 있으며, 예를 들어 컬렉션에서 가져온 델리게이트들을 쉽게 합칠 수 있습니다.


이거 글 쓰는데 3시간 걸렸다.. 블로그랑, 공식 문서랑, 지피티에 질문하며 정보가 정확한지 계속 검증해보고, 문장이 말이 되는지 안되는지도 계속 검증해봤다.
그래도 틀린 부분은 존재할 수도 있으니 참고만 해주길 바랍니다.


참고 자료

예제로 배우는 C# 프로그래밍

https://blog.hexabrain.net/151

공식문서 : MulticastDelegate 클래스

profile
개발은삼순이발

0개의 댓글