Delegate (대리자)
2022. 1. 17. 00:00ㆍCSharp/Advance
반응형
특정 매개 변수 목록 및 반환 형식이 있는 메서드에 대한 참조를 나타내는 형식.
접근제어자 + delegate + 반환형 + 대리자명 + (전달인수)
public delegate int PerformCalculation(int x, int y);
- 대리자는 C++ 함수 포인터와 유사하지만 C++ 함수 포인터와 달리 멤버 함수에 대해 완전히 개체 지향
- 대리자는 개체 인스턴스 및 메서드를 모두 캡슐화합니다.
- 대리자를 통해 메서드를 매개 변수로 전달
- 대리자를 사용하여 콜백 메서드를 정의
- 여러 대리자를 연결할 수 있다. (예를 들어 단일 이벤트에 대해 여러 메서드를 호출할 수 있다)
- 메서드는 대리자 형식과 정확히 일치하지 않아도 된다.
- 대리자 시그니처의 반환 형식에서 파생된 반환 형식이 있는 메서드와 함께 사용하는 방법 (공변성)
class Mammals {} class Dogs : Mammals {} class Program { // Define the delegate. public delegate Mammals HandlerMethod(); public static Mammals MammalsHandler() { return null; } public static Dogs DogsHandler() { return null; } static void Test() { HandlerMethod handlerMammals = MammalsHandler; // Covariance enables this assignment. HandlerMethod handlerDogs = DogsHandler; } }
- 대리자 매개 변수 형식의 기본 형식을 사용하는 매개 변수를 가지고 있는 메서드와 함께 사용하는 방법
(반공변성 을 이용하여 별도의 여러 처리기 대신 하나의 이벤트 처리기를 사용할 수 있다. )
// Button.KeyDown 이벤트를 정의하는 KeyEventHandler 대리자. public delegate void KeyEventHandler(object sender, KeyEventArgs e) // Button.MouseClick 이벤트를 정의하는 MouseEventHandler 대리자. public delegate void MouseEventHandler(object sender, MouseEventArgs e) // EventArgs 매개 변수를 사용하여 이벤트 처리기를 정의하고 // 이를 사용하여 Button.KeyDown 및 Button.MouseClick 이벤트를 모두 처리 // EventArgs는 KeyEventArgs 및 MouseEventArgs의 기본 형식이므로 이 작업을 수행할 수 있다. // Event handler that accepts a parameter of the EventArgs type. private void MultiHandler(object sender, System.EventArgs e) { label1.Text = System.DateTime.Now.ToString(); } public Form1() { InitializeComponent(); // You can use a method that has an EventArgs parameter, // Button.KeyDown 은 EventArgs 를 상속한다. this.button1.KeyDown += this.MultiHandler; // You can use the same method // Button.MouseClick 또한 EventArgs 를 상속한다. // 그러므로 아래와 같이 사용 가능하다. this.button1.MouseClick += this.MultiHandler; }
- 대리자 시그니처의 반환 형식에서 파생된 반환 형식이 있는 메서드와 함께 사용하는 방법 (공변성)
- 람다 식은 인라인 코드 블록을 작성하는 더욱 간단한 방법이다. 특정 컨텍스트에서는 람다 식이 대리자 형식으로 컴파일된다.
예제)
public class Delegates
{
// Delegate type 선언
public delegate Shape CreateShapeDelegate();
public delegate void AddCircleDelegate(Circle e);
public delegate void AddRectangleDelegate(Rectangle e);
public delegate void AddTriangleDelegate(Triangle e);
public interface IShape
{
public CreateShapeDelegate CreateShape { get; set; }
}
public class Shape
{
public Shape() => PrintDraw();
protected virtual string GetClassName() => GetType().Name;
protected virtual void PrintDraw() => Console.WriteLine($"Drawing a {GetClassName()}");
}
public class Circle : Shape { }
public class Rectangle : Shape { }
public class Triangle : Shape { }
public class Creator
{
// call back 용
public AddCircleDelegate? AddCircleDelegateHandler;
public AddRectangleDelegate? AddRectangleDelegateHandler;
public AddTriangleDelegate? AddTriangleDelegateHandler;
// multi cast
public CreateShapeDelegate? MultiAction;
public Shape MakeShape() => new Shape();
public Circle MakeCircle() => new Circle();
public Rectangle MakeRectangle() => new Rectangle();
public Triangle MakeTriangle() => new Triangle();
public void Test()
{
// 공변성 Test
MultiAction = MakeShape;
MultiAction += MakeCircle;
MultiAction += MakeRectangle;
MultiAction += MakeTriangle;
MultiAction -= MakeCircle;
Console.WriteLine("MultiAction test");
MultiAction();
Console.WriteLine();
Console.WriteLine("Message fire test");
AddCircleDelegateHandler?.Invoke(new Circle());
AddRectangleDelegateHandler?.Invoke(new Rectangle());
AddTriangleDelegateHandler?.Invoke(new Triangle());
}
}
public class Test : ITest
{
List<Shape> _shapes = new List<Shape>();
Creator creator = new Creator();
public CreateShapeDelegate? CallGetShape;
public void Run()
{
//creator.AddCircleDelegateHandler += OnAddCircle;
//creator.AddRectangleDelegateHandler += OnAddRectangle;
//creator.AddTriangleDelegateHandler += OnAddTriangle;
// 반공변성 Test (모두 OnAddMultiHandler 에서 처리)
creator.AddCircleDelegateHandler += OnAddMultiHandler;
creator.AddRectangleDelegateHandler += OnAddMultiHandler;
creator.AddTriangleDelegateHandler += OnAddMultiHandler;
creator.Test();
}
public void OnAddCircle(Circle circle)
{
Console.WriteLine($"adding {circle.GetType().Name} in List<Shape>");
_shapes.Add(circle);
Console.WriteLine($"added {circle.GetType().Name} in List<Shape>");
}
public void OnAddRectangle(Rectangle rectangle)
{
Console.WriteLine($"adding {rectangle.GetType().Name} in List<Shape>");
_shapes.Add(rectangle);
Console.WriteLine($"added {rectangle.GetType().Name} in List<Shape>");
}
public void OnAddTriangle(Triangle triangle)
{
Console.WriteLine($"adding {triangle.GetType().Name} in List<Shape>");
_shapes.Add(triangle);
Console.WriteLine($"added {triangle.GetType().Name} in List<Shape>");
}
public void OnAddMultiHandler(Shape shape)
{
Console.WriteLine($"adding {shape.GetType().Name} in List<Shape>");
_shapes.Add(shape);
Console.WriteLine($"added {shape.GetType().Name} in List<Shape>");
}
}
}
Add (+=)
MultiAction += MakeCircle;
Remove (-=)
MultiAction -= MakeCircle;
관련영상
반응형
'CSharp > Advance' 카테고리의 다른 글
제네릭 컬렉션 (Generic Collection) (0) | 2022.01.24 |
---|---|
Record (0) | 2022.01.21 |
Lambda advanced (0) | 2022.01.20 |
Action, Func, Lambda (0) | 2022.01.19 |
Event (이벤트) (0) | 2022.01.18 |