C#프로그래밍 18 : 대리자

LeeWonjin·2022년 5월 26일
0

[학부]C#프로그래밍

목록 보기
18/21

대리자 개념

개념

  • 메소드에 대한 참조 (대리자 호출을 통해 메소드 호출)
  • 인스턴스가 아닌 데이터 타입

선언

delegate키워드로 선언

한정자 delegate 반환형 대리자식별자(매개변수);

인스턴스 생성 및 호출

인스턴스를 만들 때 함수 식별자를 생성자에 넣어줌.
이 때, 아래 두 개가 같아야함.

  • 인수로 들어간 함수의 매개변수의 개수, 타입
  • 대리자에 정의된 매개변수의 개수, 타입

인스턴스에 메소드를 연결할 때는 두 가지 방법이 있음

  • 생성자 호출로 연결
  • 함수식별자를 직접 대입해 연결

대리자 인스턴스 DelgInstance1, DelgInstance2를 호출하면 메소드 Add, Multiply가 호출됨.

class Program
{
    delegate int Delg(int a, int b);
    static int Add(int x, int y){
        return x+y;
    }
    static int Multiply(int x, int y){
        return x*y;
    }
    static void Main(string[] args)
    {
        Delg DelgInstance1;
        DelgInstance1 = new Delg(Add); // 생성자 호출로 대입
        int result1 = DelgInstance1(5, 3);
        Console.Write(result1); // 8
        
        Dleg DelgInstance2;
        DelgInstance2 = Multiply; // 생성자 없이 직접 대입
        int result2 = DelgInstance2(5, 3);
        Console.Write(result2); // 15
    }
}

매개변수로서 대리자 사용

class Program
{
    delegate string GetSound(int reps);

    static string Gorani(int reps)
    {
        string sound = "kaawawaak ";
        string res = "";
        for (int i = 0; i < reps; i++) res += sound;
        return res;
    }
    static string Cat(int reps)
    {
        string sound = "yaong ";
        string res = "";
        for (int i = 0; i < reps; i++) res += sound;
        return res;
    }

    static void PrintSound(GetSound SoundGetter, int reps)
    {
        string str = SoundGetter(reps);
        Console.WriteLine(str);
    }

    static void Main(string[] args)
    {
        PrintSound(new GetSound(Gorani), 2); // kaawawaak kaawawaak
        PrintSound(new GetSound(Cat), 3); // yaong yaong yaong
    }
}

일반화 대리자

그냥 <T\>붙어있음.

IComparable<T>를 상속받은 클래스는 a.CompareTo(b)메소드를 구현함.
a>b이면 1
a=b이면 0
a<b이면 -1

class Program
{
    delegate T Get<T>(T a, T b); // a와 b는 같지 않다고 가정

    static T GetBig<T>(T a, T b) where T : IComparable<T>
    {
        return (a.CompareTo(b)) == 1 ? a : b;
    }
    static T GetSmall<T>(T a, T b) where T : IComparable<T>
    {
        return (a.CompareTo(b)) == 1 ? b : a;
    }

    static void Main(string[] args)
    {
        Get<int> X = GetBig<int>;
        Console.WriteLine(X(5,3)); // 5

        Get<float> Y = GetSmall<float>;
        Console.WriteLine(Y(5.3f, 3.5f)); // 3.5
    }
}

대리자 체인

대리자 하나가 여러 개의 메소드를 참조하게 하는 방법

체인 결합 방법 (추가)

  • +=, +연산자
  • .Combine메소드

체인 끊기 방법 (제거)

  • -=연산자
  • .Remove메소드
namespace Program
{
    delegate void Delg(int a, int b);

    class Program
    {
        static void Add(int a, int b)
        {
            Console.WriteLine(a + b);
        }
        static void Subtract(int a, int b)
        {
            Console.WriteLine(a - b);
        }
        static void Multiply(int a, int b)
        {
            Console.WriteLine(a * b);
        }
        static void Divide(int a, int b)
        {
            Console.WriteLine(a / b);
        }

        static void Main(string[] args)
        {
            Delg DelgInstance = Add;
            DelgInstance += Subtract;
            DelgInstance += new Delg(Multiply) + new Delg(Divide);
            DelgInstance(5, 3); // 8 2 15 1

            Console.WriteLine("-----");
            DelgInstance -= Subtract;
            DelgInstance -= Multiply;
            DelgInstance = (Delg)Delegate.Remove(DelgInstance, new Delg(Divide));
            DelgInstance(5, 3); // 8

            Console.WriteLine("-----");
            DelgInstance = (Delg)Delegate.Combine(DelgInstance, new Delg(Subtract));
            DelgInstance(5, 3); // 8 2
        }
    }
}

익명 메소드

이름없는 익명 메소드를 대리자 인스턴스에 연결하여 사용 가능

class Program
{
    delegate void Delg(int x);
    
    static void Main(string[] args)
    {
        Delg multiplyTwo = delegate (int a)
        {
            Console.WriteLine(a * 2);
        };

        multiplyTwo(53); // 106
    }
}

이벤트

생성

대리자를 event한정자로 수식

delegate void EventHandler(int a);
class Program
{
    public event EventHandler Handler;
}

특징

이벤트가 선언된 클래스 밖에서

  • 이벤트 호출(발생) 불가
  • 해당 이벤트에 핸들러 등록/해지 가능

.NET에 정의된 EventHandler

public delegate void EventHandler(object? sender, EventArgs e);
profile
노는게 제일 좋습니다.

0개의 댓글