C# Delegate (Action, Func, Event)
π« Q
- λ리μ
- λ리μλ₯Ό μ μΈνκ³ μ¬μ©νλ λ°©λ²
- λ리μκ° μ¬μ©λλ μ΄μ μ μν©
- μΌλ°ν λ리μλ₯Ό μμ±νκ³ μ¬μ©νλ λ°©λ²
- μ΅λͺ λ©μλλ₯Ό μ μΈνκ³ μ¬μ©νλ λ°©λ²
- μ΄λ²€νΈλ₯Ό μ μΈνκ³ μ¬μ©νλ λ°©λ²
π« Delegate | λ리μ
λ©μλμ μ°Έμ‘°.
Like ν¨μ ν¬μΈν° in C/C++.
λ©μλλ₯Ό λ³μμ²λΌ μΈ μ μκ² ν΄μ€λ€ !
λ©μλλ₯Ό λ³μμ ν λΉνκ³ , λ€λ₯Έ λ©μλμ μΈμλ‘ μ λ¬νκ±°λ λ°ν κ°μΌλ‘ μ¬μ©ν μ μλ€.
μ£Όλ‘ μ΄λ²€νΈ μ²λ¦¬, λΉλκΈ° μ²λ¦¬, μ½λ°± ν¨μλ₯Ό ꡬνν λ μ¬μ©λλ€.
𫧠Delegate ꡬν
delegate λ°ννμ
MyDelegate(맀κ°λ³μ);
κ°μ λͺ¨μμΌλ‘ μ μΈνλ€.
맀κ°λ³μλ νμν λ§νΌ μ μΈν μ μλ€. (0 ~ 16κ°)
μ£Όμ !!
delegate
λ int
, string
κ°μ νμ(Type)μ΄λ―λ‘,
βλ©μλλ₯Ό μ°Έμ‘°νλ κ·Έ 무μβμ λ§λ€λ €λ©΄ μΈμ€ν΄μ€λ₯Ό λ°λ‘ λ§λ€μ΄μΌ νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// μ μΈ
delegate void MyDelegate(string msg);
// μ μ
void Method1(string msg) => Console.WriteLine(msg);
// μΈμ€ν΄μ€ μμ±
MyDelegate myDelegate = new MyDelegate(Method1);
// νΈμΆ
myDelegate("Hello, World!");
// Output :
// Hello, World!
𫧠Delegate Why?
βκ°βμ΄ μλ βνλβ, βμ½λβ μ체λ₯Ό μ λ¬νκ³ μΆμ λκ° μλ€.
μλ₯Ό λ€μ΄ λ°°μ΄μ μ λ ¬νλ λ©μλλ₯Ό λ§λ€ λ,
μ€λ¦μ°¨μμΌλ‘ μ λ ¬ν μ§, λ΄λ¦Όμ°¨μμΌλ‘ μ λ ¬ν μ§, νΉλ³ν κ³μ°μμ μΈμ§..
μ λ ¬μ μνν λ μ¬μ©νλ λΉκ΅ 루ν΄μ λ§€κ° λ³μλ‘ λ£μ μ μλ€λ©΄?
μ΄λ° κ³ λ―Όμ λ©μλλ₯Ό μ¬μ©νλ νλ‘κ·Έλλ¨Έκ° μμμ κ²°μ ν μ μλ€.
𫧠Delegate μΌλ°ν
λ³΄ν΅ λ©μλ λΏλ§ μλλΌ, μΌλ°ν λ©μλλ μ°Έμ‘°ν μ μλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// μ μΈ
// IComparable : λΉκ΅ κ°λ₯ν νμ
(μμΉν, λ¬Έμμ΄)
// IComparable.CompareTo() : λΉκ΅ λ©μλ (1, 0, -1)
delegate T MyDelegate<T>(T a, T b) where T : IComparable;
// μ μ
int Add(int a, int b) => a + b;
float Add(float a, float b) => a + b;
// μΈμ€ν΄μ€ μμ±
MyDelegate<int> myDelegate1 = Add;
MyDelegate<float> myDelegate2 = Add;
// νΈμΆ
int result1 = myDelegate(1, 2);
float result2 = myDelegate(1.0f, 2.0f);
// Output :
// 3
// 3.0
𫧠Delegate 체μΈ
νλμ delegate
μ μ¬λ¬ λ©μλλ₯Ό ν λΉν μ μλ€.
κ·Έλ κ² ν λΉν μ¬λ¬ λ©μλλ₯Ό νλ²μ νΈμΆν μ μλ€. (λ©ν°μΊμ€νΈ)
νΈμΆ μμλ ν λΉλ μμλλ‘ νΈμΆλλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// μ μΈ
delegate void MyDelegate(string msg);
// μ μ
void Method1(string msg) => Console.WriteLine(msg);
void Method2(string msg) => Console.WriteLine(msg);
// μΈμ€ν΄μ€ μμ±
MyDelegate myDelegate;
// 1. ν λΉ (+=) / ν΄μ (-=)
myDelegate += Method1;
myDelegate += Method2;
// 2. ν λΉ (+) / ν΄μ (-)
myDelegate = Method1 + Method2;
// 3. ν λΉ (Delegate.Combine) / ν΄μ (Delegate.Remove)
myDelegate = (MyDelegate) Delegate.Combine(
new MyDelegate(Method1),
new MyDelegate(Method2));
// νΈμΆ
myDelegate("Hello, World!");
// Output :
// Hello, World!
// Hello, World!
𫧠Delegate μ΅λͺ λ©μλ / 무λͺ ν¨μ νμ©
μ΅λͺ λ©μλμ 무λͺ ν¨μλ₯Ό μ¬μ©ν μ μλ€.
μ°Έκ³ λ‘ μ΅λͺ
λ©μλλ C# 2.0μμ, 무λͺ
ν¨μλ C# 3.0μμ λμ
λμλ€.
무λͺ
ν¨μκ° νΈλ¦¬νμ§λ§, νμ νΈνμ±μ μ μ§νκΈ° μν΄ λ κ°μ§ λ°©λ²μ λͺ¨λ μ§μνκ³ μλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// μ μΈ
delegate void MyDelegate(string msg);
// μΈμ€ν΄μ€ μμ±
MyDelegate myDelegate;
// μ΅λͺ
λ©μλ ν λΉ
myDelegate = delegate (string msg) { Console.WriteLine(msg); };
// 무λͺ
ν¨μ ν λΉ
myDelegate += (string msg) => { Console.WriteLine(msg); };
// νΈμΆ
myDelegate("Hello, World!");
// Output :
// Hello, World!
// Hello, World!
𫧠Delegate λΉλκΈ° μ²λ¦¬ (Invoke/BeginInvoke)
Invoke
λ BeginInvoke
, EndInvoke
λ₯Ό μ΄μ©ν΄ λΉλκΈ° μ²λ¦¬λ₯Ό ν μ μλ€.
μΈ μλ μμ§λ§ μ€λλ λ°©μμ΄λ―λ‘, λΉλκΈ° μ²λ¦¬λ Task
λ₯Ό μ°λ κ²μ΄ λ λ°λμ§νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// https://www.csharpstudy.com/Threads/async-delegate.aspx
// μ μΈ λ° μΈμ€ν΄μ€ μμ±
Func<int, int, int> work = GetArea;
// μ μ
int GetArea(int height, int width)
{
int area = height * width;
return area;
}
// λΉλκΈ° μ²λ¦¬
IAsyncResult asyncRes = work.BeginInvoke(10, 20, null, null);
int result = work.EndInvoke(asyncRes);
π« μΌλ°νλ Delegate
μΌμΌμ΄ delegate
λ₯Ό μ μνλ κ²μ΄ λ²κ±°λ‘λ€λ©΄,
Action
, Func
, Predicate
λ±μ μ¬μ©ν μ μλ€.
𫧠Action
delegate
μ μΌλ°νλ‘, λ°ν κ°μ΄ μλ(void
) λ©μλλ₯Ό μ°Έμ‘°ν μ μλ delegate
.
맀κ°λ³μλ 0 ~ 16κ°κΉμ§ μ μΈν μ μλ€.
κ·Έ μ΄μμ 맀κ°λ³μλ₯Ό μ¬μ©νκ±°λ, ref
λ out
νμ μλ‘ μμλ λ§€κ° λ³μλ₯Ό μ¬μ©ν΄μΌ νλ κ²½μ°λΌλ©΄ μ§μ λ³λμ λ리μλ₯Ό λ§λ€μ΄ μ¨μΌνλ€.
1
2
3
4
5
Action<string> myAction = (msg) => Console.WriteLine(msg);
myAction("Hello, World!"); // Hello, World!
Action<int, int> myAction = (a, b) => a + b;
myAction(1, 2); // 3
𫧠Func
delegate
μ μΌλ°νλ‘, λ°ν κ°μ΄ μλ(void
μ μΈ) λ©μλλ₯Ό μ°Έμ‘°ν μ μλ delegate
.
맀κ°λ³μλ 0 ~ 16κ°κΉμ§ μ μΈν μ μκ³ , λ§μ§λ§ 맀κ°λ³μκ° λ°ν κ°μ΄ λλ€.
κ·Έ μ΄μμ 맀κ°λ³μλ₯Ό μ¬μ©νκ±°λ, ref
λ out
νμ μλ‘ μμλ λ§€κ° λ³μλ₯Ό μ¬μ©ν΄μΌ νλ κ²½μ°λΌλ©΄ μ§μ λ³λμ λ리μλ₯Ό λ§λ€μ΄ μ¨μΌνλ€.
1
2
Func<int, int, int> myFunc = (a, b) => a + b;
myFunc(1, 2); // 3
𫧠Predicate
Func
μ νΉμν ννλ‘, λ°ν κ°μ΄ bool
μΈ delegate
.
νλμ 맀κ°λ³μλ₯Ό λ°μ bool
κ°μ λ°ννλ€.
1
2
Predicate<int> myPredicate = (num) => num > 0;
myPredicate(1); // True
π« Event | μ΄λ²€νΈ
μ΄λ²€νΈ(μ¬κ±΄)
λ₯Ό ꡬννκΈ° μν΄ λͺ κ°μ§ μ μ½μ κ°μ§, λνλ delegate
.
μ΄λ²€νΈ | κ°μ²΄μ μΌμ΄λ μ¬κ±΄ μ리기
κ°μ²΄μ μν λ³ν, μ¬κ±΄μ λ°μμ λ€λ₯Έ κ°μ²΄λ λ©μλμ μ리기 μν΄ μ¬μ©λλ€.
λ€λ₯Έ κ°μ²΄λ λ©μλμμ μ΄λ²€νΈλ₯Ό ꡬλ
νκ³ , μ΄λ²€νΈκ° λ°μνλ©΄ μλ¦Όμ λ°μ μ²λ¦¬ν μ μλ€.
𫧠Eventκ° Delegateμ λ€λ₯Έ μ
event
λ μΈλΆμμ μ§μ νΈμΆν μ μλ€.delegate
λpublic
μ΄λinternal
λ‘ μμλμ΄ μμΌλ©΄ κ°λ₯νλ€.
delegate
λinterface
λ΄λΆμμ μ¬μ©ν μ μμ§λ§,event
λinterface
λ΄λΆμμ μ¬μ©ν μ μλ€.event
λdelegate
μ μΈμ€ν΄μ€μ΄κΈ° λλ¬Έμ΄λ€.
𫧠Event ꡬν
delegate
λ₯Ό event
ν€μλλ‘ μμν΄μ μ μΈνλ€.
μ΄λ μμλλ delegate
λ ν΄λμ€ λ°μ μ μΈν΄λ λκ³ μμ μ μΈν΄λ λλ€.
event
λ μ μΈν delegate
μ μΈμ€ν΄μ€μ΄λ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// delegate μ μΈ (ν΄λμ€ λ°μ μ μΈν΄λ λλ€.)
delegate void MyDelegate(string msg);
// Publisher
class MyClass
{
// μ΄λ²€νΈ μ μΈ (MyDelegateμ μΈμ€ν΄μ€)
public event MyDelegate MyEvent;
// ꡬλ
& ꡬλ
ν΄μ
public void Subscribe(MyDelegate myDelegate) => MyEvent += myDelegate;
public void Unsubscribe(MyDelegate myDelegate) => MyEvent -= myDelegate;
// μ΄λ²€νΈ λ°μ (μ΄λ²€νΈλ ν΄λμ€ λ΄λΆμμλ§ νΈμΆ κ°λ₯)
public void OnEvent(string msg) => MyEvent?.Invoke(msg);
}
// Subscriber
class Program
{
static void Main()
{
MyClass myClass = new MyClass();
myClass.Subscribe(MyMethod);
myClass.OnEvent("Hello, World!");
// μλμ²λΌ μ΄λ²€νΈλ₯Ό μΈλΆμμ μ§μ νΈμΆ ν μ μλ€.
// myClass.MyEvent?.Invoke("Hello, World!");
}
static void MyMethod(string msg) => Console.WriteLine(msg);
}
1
2
// Static Eventμ μ¨λ³΄λ κ²λ κ³ λ €. (νΉν Singleton Pattern)
public static event EventHandler MyEvent;
1
2
3
4
5
6
7
8
// ꡬλ
νλ Delegateμ μ΄λ¦μ On + μ΄λ²€νΈ μ΄λ¦μΌλ‘ μ§λ κ²μ΄ κ΄λ‘
public void OnMyEvent(string msg) => MyEvent?.Invoke(this, new MyEventArgs(msg));
// μ΄λ²€νΈλ₯Ό λ°μμν€λ λ©μλλ Raise + μ΄λ²€νΈ μ΄λ¦μΌλ‘ μ§λ κ²μ΄ κ΄λ‘
public void RaiseMyEvent(string msg) => OnMyEvent(msg);
// μ΄λ²€νΈ νΈλ€λ¬μ μ΄λ¦μ μ΄λ²€νΈ μ΄λ¦ + EventHandlerλ‘ μ§λ κ²μ΄ κ΄λ‘
public void MyEventHandler(object sender, MyEventArgs e) => Console.WriteLine(e.Message);
π« λ©λͺ¨
- callbackμ ꡬννλ λ°©λ².
- delegateλ μμ΄λ‘ βλ리μΈβ, βμ¬μ β μ΄λΌλ λ»μ΄ μλ€.
delegate
λ₯Ό μ΄μ©ν΄ ν¨μν νλ‘κ·Έλλ°μ μΌκΈ κ°μ²΄λ‘μμ ν¨μ κ°λ μ ꡬνν μ μλ€.delegate
(event
)λ₯Ό μ΄μ©ν΄ μ΄λ²€νΈ, μ΅μ λ² ν¨ν΄μ ꡬνν μ μλ€.- βμ΄κ²μ΄ C#μ΄λ€.β, βMSDNβ
- EventEvent-Driven-Programming
- Lambda-Expression