• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

Delegate가 헷갈려요

21.02.04 10:33 작성 조회수 359

0

안녕하세요

3번째 파트, 유니티 듣다가 C# 문법들이 헷갈려서 유니티 파트 들으면서 C#도 복습중에 있습니다

그러다 Delegate를 다시 듣는데 좀 헷갈려서요

헷갈리는 이유는 아무래도 접한 순서 때문이거 같아요

저는 event를 먼저 배워버려서 이쪽이 가지는 인상이 너무 큰거 같아요

저에게 이벤트는 변수 선언할 때, Event 붙이고, 다른 클래스에서 해당 event에 접속한다음에 += 붙여서 필요한 함수(함수 A)를 구독시킨다ㅣ

여기서 추가로, Event를 통해서 함수A에가다가 추가 정보를 전달해주고 싶으면 EventArgs를 생성해서 넘겨준다 대신, 구독하는 함수A 또한 EventArgs의 형식을 인자로 가져야 한다인데요 (설명이 부정확한 점은 양해 부탁드립니다)

글을 쓰다보니까 이해를 하는 단계인거 같은데

느낌상, Delegate를 사용하면 2가지의 단계가 있는거 같아요예를 들자면

void OnButtonPressed(CalScore calScore)

{

    calScore();

}// 버튼이 눌리면 호출 되는 함수

int _score = 0;

delegate int CalScore(int score)

CalScore calScore = new Calscore(AddScore(3));

calScore += RemoveScore(2);

public int AddScore(int score)

{

    _score += score;

}

public int RemoveScore(int score)

{

    _score -= score;

}

static void Main(sting[] args)

{

    OnButtonPressed(calScore)

}

이 경우엔, delegate의 인스턴스인 calScore는 이 delegate 형식을 따르는 함수들의 연산 결과물을 담아두고 있는 바구니 같아요. (단계1) 그리고 이 친구를 인자로 받겠다고 한 OnButtonPressed()는 말 그대로 이 delegate 인스턴스를 받아서 이 녀석이 가지고 있는 연산 결과물을 꺼내주는거죠(단계2)

또 다시 글을 쓰다보니까 생각이 드는게

처음에 함수를 인자로 넘겨준다고 하셔서 저는 그 말대로

OnButtonPressed(AddScore(3))가 될 거라고 생각을 했습니다 

그런데 곰곰히 생각을 해보니까 그게 아니라

delegate라는 녀석이 두 종류의 함수 사이에서 교두보 역할을 해주는거 같아요

글이 너무 두서가 없어서 죄송합니다

제가 똑바로 이해한게 맞나요?

답변 3

·

답변을 작성해보세요.

0

그렇게 보는 것도 맞는 관점이긴 합니다.
물론 가장 일반적인 해석은 nested 호출 자체에 있다기 보다는
'함수를 인자처럼 사용하는' 것에 중점을 둡니다.
함수를 호출할 때, 호출할 다른 함수를 인자로 받는 것을
Functional Programming이라고 하는데
그것을 구현하기 위한 기초라고 할 수 있겠네요.
함수를 인자처럼 사용할 수 있으니 다른 함수에도 넘겨줄 수 있고,
또 잠시 그 함수를 기억하고 있다가 한참 후에 호출하는 것도 가능하겠죠(observer 패턴).

0

Hyobin Kim님의 프로필

Hyobin Kim

질문자

2021.02.05

답변 달아주신거랑 그 다음 강의 Lambda를 보고 있는데 여기서 delegate 쓰시는거 보고 또 이해에 진전이 있었습니다

처음에, delegate는 함수를 인자로 넘기기 위한거다 라는것에 더 중점을 뒀어야 했나봅니다

제가 이해해서 내리는 정의를 써보면

delegate는 (이런 말 없을것 같지만) nested methods를 가능하게 해주는 수단이라고 봐야겠습니다

기능이 전혀 다른 함수들이 있는데 이들이 서로 연계되어 겹쳐져서 (nested) 사용될 때 delegate가 필요하다 

delegate를 인자로 받는 함수와 delegate를 따르는 함수가 있으면 

첫번째 함수안에서 두번째 함수가 돌아가는거다

이런식으로 이해하면 되나요?

0

저에게 이벤트는 변수 선언할 때, Event 붙이고, 다른 클래스에서 해당 event에 접속한다음에 += 붙여서 필요한 함수(함수 A)를 구독시킨다
여기서 추가로, Event를 통해서 함수A에가다가 추가 정보를 전달해주고 싶으면 EventArgs를 생성해서 넘겨준다 대신, 구독하는 함수A 또한 EventArgs의 형식을 인자로 가져야 한다인데요 (설명이 부정확한 점은 양해 부탁드립니다)

-> event랑 delegate는 크게 다른 개념이 아닙니다.
event에서 이해하신 내용이 delegate에도 그대로 적용이 됩니다.
'기본적'으로 event나 delegate 양쪽 모두
동일한 시그니처 (입력/출력 타입)를 갖는 함수를 저장하고 있다가
때가 오면 대신 호출해주는 개념인데요.
어디까지 '함수'를 기억하는 것이지 각 '인자'를 기억하진 못합니다.
그러다 보니 위에서 

CalScore calScore = new Calscore(AddScore(3));
calScore += RemoveScore(2);

와 같이 함수 + 인자까지 같이 세팅해준 형태로 넘겨주면 컴파일이 되지 않습니다. 
기본적으로 calcScore에는 연결된 함수 AddScore, RemoveScore를 등록하고,
calcScore(2); 와 같이 event 나 delegate를 호출하는 순간
인자를 같이 넘겨주는 쪽에 가깝습니다.

추가로 '기본적'이라고 한 이유는 함수뿐 아니라
인자도 같이 묶어서 넘겨줄 수 있는 방법이 존재하기 때문인데요.
아래부터 좀 어려운 내용이니 이해가 안 가시면 일단 넘어가도 됩니다.

-------------------------------------

조금 복잡한 내용인데 lambda를 사용할 때 [캡쳐] 기능이라는 것이 있습니다.
카메라가 사진을 찰칵 찍듯 내가 원하는 값을 저장했다가
함수에 같이 넘겨주는 것인데요.

기본적으로 lambda는 '이름이 없는 함수'이기 때문에
calcScore가 요구하는 시그니처 (int 1개를 받고, int 를 return)로 맞춰주고 있습니다.
(그래서 위에서 (num)을 인풋으로, return 0으로 일단 임시 세팅한거구요)

여기서 놀라운 사실은 AddScore(2)와 같이,
람다식 안에서 우리가 원하는 인자를 같이 넘길 수 있다는 것입니다.
그리고 이렇게 인자 2를 저장할 수 있는 이유는
내부적으로는 단일 함수만 딱 저장하는게 아니라
함수 + 인자 세트로 만들어지는 어떤 객체가 만들어지기 때문입니다.
느낌적인 느낌으로 다음과 같습니다.

class Lambda_4124
{
   int _temp = 2;

   public int Invoke(int num)
   {
     AddScore(_temp);
     return 0;
   }
}