ํฌ์ŠคํŠธ

C# Delegate (Action, Func, Event)

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์™€ ๋‹ค๋ฅธ ์ 

  1. event๋Š” ์™ธ๋ถ€์—์„œ ์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค.
    • delegate๋Š” public์ด๋‚˜ internal๋กœ ์ˆ˜์‹๋˜์–ด ์žˆ์œผ๋ฉด ๊ฐ€๋Šฅํ•˜๋‹ค.
  2. 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);
}

๐Ÿ’ซ ๋ฉ”๋ชจ/์ฐธ๊ณ 


  • callback์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•.
  • delegate๋Š” ์˜์–ด๋กœ โ€œ๋Œ€๋ฆฌ์ธโ€, โ€œ์‚ฌ์ ˆโ€ ์ด๋ผ๋Š” ๋œป์ด ์žˆ๋‹ค.
  • delegate๋ฅผ ์ด์šฉํ•ด ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ผ๊ธ‰ ๊ฐ์ฒด๋กœ์„œ์˜ ํ•จ์ˆ˜ ๊ฐœ๋…์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • delegate (event)๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ, ์˜ต์ €๋ฒ„ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • โ€˜์ด๊ฒƒ์ด C#์ด๋‹ค.โ€™, โ€˜MSDNโ€™
  • TODO: ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

  • Lambda-Expression
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.