2022. 1. 19. 00:00ㆍCSharp/Advance
Action
매개 변수가 없고 값을 반환하지 않는 메서드를 캡슐화 한 대리자 (delegate)
Action<T>
매개 변수가 하나이고 값을 반환하지 않는 메서드를 캡슐화 한 대리자 (delegate)
Action<T1, ..... Tn>
매개 변수가 n 개이고 값을 반환하지 않는 메서드를 캡슐화 한 대리자 (delegate)
(n = 최대 16, 입력 가능 parameter 가 16개까지 가능하다.)
Func<TResult>
매개 변수가 없고 TResult 매개 변수에 지정된 형식의 값을 반환하는 메서드를 캡슐화 한 대리자 (delegate)
Func<T, TResult>
매개 변수가 하나이고 TResult 매개 변수에 지정된 형식의 값을 반환하는 메서드를 캡슐화 한 대리자 (delegate)
Func<T1, .... Tn, TResult>
매개 변수가 n 개이고 TResult 매개 변수에 지정된 형식의 값을 반환하는 메서드를 캡슐화 한 대리자 (delegate)
(n = 최대 16, 입력 가능 parameter 가 16개까지 가능하다.)
이 두 가지 Generic delegate type 을 이용해서 delegate type을 따로 선언(정의) 하지 않고 사용 가능하다.
이전 delegate 에서 사용한 code 를 Action, Func 을 사용하여 수정해 보자.
public class Action_Func
{
// 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 class Shape
{
public Shape()
{
PrintDraw();
}
protected virtual string GetClassName()
{
return 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 method call
//public CreateShapeDelegate? MultiAction;
//Func 와 Action 을 사용하여 수정
public Func<Shape> MultiAction;
public Action<Circle> AddCircleDelegateHandler;
public Action<Rectangle> AddRectangleDelegateHandler;
public Action<Triangle> AddTriangleDelegateHandler;
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 void Run()
{
//creator.AddCircleDelegateHandler += OnAddCircle;
//creator.AddRectangleDelegateHandler += OnAddRectangle;
//creator.AddTriangleDelegateHandler += OnAddTriangle;
creator.Test();
// 반공변성 Test (모두 OnAddShape 에서 처리)
creator.AddCircleDelegateHandler += OnAddMultiHandler;
creator.AddRectangleDelegateHandler += OnAddMultiHandler;
creator.AddTriangleDelegateHandler += OnAddMultiHandler;
}
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>");
}
}
}
delegate type 선언 부분이 주석 처리 되었고
// Delegate type 선언
//public delegate Shape CreateShapeDelegate();
//public delegate void AddCircleDelegate(Circle e);
//public delegate void AddRectangleDelegate(Rectangle e);
//public delegate void AddTriangleDelegate(Triangle e);
delegate type 을 사용하여 변수를 정의 하는 부분 또한 주석 처리 되고 다음과 같이 변경되었다.
//// call back 용
//public AddCircleDelegate? AddCircleDelegateHandler;
//public AddRectangleDelegate? AddRectangleDelegateHandler;
//public AddTriangleDelegate? AddTriangleDelegateHandler;
//// multi method call
//public CreateShapeDelegate? MultiAction;
//Func 와 Action 을 사용하여 수정
public Func<Shape> MultiAction;
public Action<Circle> AddCircleDelegateHandler;
public Action<Rectangle> AddRectangleDelegateHandler;
public Action<Triangle> AddTriangleDelegateHandler;
Lambda Expressions
익명 함수를 만드는 방법입니다.
//식이 본문으로 포함된 식 람다 (Expression lambda)
(input-parameters) => expression
//문 블록이 본문으로 포함된 문 람다 (Statement lambda)
(input-parameters) => { <sequence-of-statements> }
간단한 람다식
Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
// Output:
// 25
Expression Tree 형식으로 변환도 가능
System.Linq.Expressions.Expression<Func<int, int>> e = x => x * x;
Console.WriteLine(e);
// Output:
// x => (x * x)
Linq 문을 작성할 때 람다 식을 사용하기도 함
int[] numbers = { 2, 3, 4, 5 };
var squaredNumbers = numbers.Select(x => x * x);
Console.WriteLine(string.Join(" ", squaredNumbers));
// Output:
// 4 9 16 25
람다식을 사용하여 위에 Action , Func 로 이루어진 코드를 변경해 보자
public class LambdaExpressions
{
public class Shape
{
public Shape()
{
PrintDraw();
}
protected virtual string GetClassName()
{
return 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
{
//Func 와 Action 을 사용하여 수정
public Func<Shape> MultiAction;
public Action<Circle> AddCircleDelegateHandler;
public Action<Rectangle> AddRectangleDelegateHandler;
public Action<Triangle> AddTriangleDelegateHandler;
public void Test()
{
// 공변성 Test
// lambda 식을 이용하여 적용
MultiAction = () => new Shape();
MultiAction += () => new Circle();
MultiAction += () => new Rectangle();
MultiAction += () => new Triangle();
MultiAction -= () => new Circle();
// lambda 식을 사용할 경우 -= 를 통한 remove 동작은
// 이전 lambda 식을 가르킬수 있는 방법이 없으므로 동작하지 않는다.
// event 등록 및 삭제 시에 많이 하는 실수 이므로 주의하자
// 이로인해 memory leak 이 발생하는 경우가 많다.
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 void Run()
{
// lambda 식으로 처리
// 아래와 같은 경우는 lambda 식이 중복 되므로
// 다음과 같이 처리 하자
Action<Shape> multiAction = shape =>
{
Console.WriteLine($"adding {shape.GetType().Name} in List<Shape>");
_shapes.Add(shape);
Console.WriteLine($"added {shape.GetType().Name} in List<Shape>");
};
creator.AddCircleDelegateHandler += multiAction;
creator.AddRectangleDelegateHandler += multiAction;
creator.AddTriangleDelegateHandler += multiAction;
creator.Test();
}
}
}
관련영상
'CSharp > Advance' 카테고리의 다른 글
제네릭 컬렉션 (Generic Collection) (0) | 2022.01.24 |
---|---|
Record (0) | 2022.01.21 |
Lambda advanced (0) | 2022.01.20 |
Event (이벤트) (0) | 2022.01.18 |
Delegate (대리자) (0) | 2022.01.17 |