using System;
class Program
{
// 델리게이트 정의
public delegate int MyCallback(int a, int b);
// 덧셈 메서드
static int Add(int a, int b)
{
return a + b;
}
// 곱셈 메서드
static int Multiply(int a, int b)
{
return a * b;
}
static void Main(string[] args)
{
MyCallback MathOperation;
MathOperation = Add;
Console.WriteLine(MathOperation(3, 4));
MathOperation = Multiply;
Console.WriteLine(MathOperation(7, 5));
}
}
내 답:
7
35
int 매개변수 두 가지를 받아서 동작하는 MyCallback이라는 delegate를 정의하고 구동 단계에서 MathOperation으로 delegate를 만들어 Console.WriteLine으로 출력시키기 전에 각각 Add 메서드와 Multiply 메서드를 delegate에 할당시켰기 때문입니다.
모범 답:
위 코드를 보면 MathOperation = Add; 를 통해 객체로 만들어진 MathOperation에 정적으로 만들어진 Add 메서드를 가리키도록 설정되어있다. 따라서 해당 MathOperation은 Add와 동일한 작동을 하며, MathOperation의 매개변수에 값을 넣어 반환하게 된다. 따라서 MathOperation = Add;의 값은 3+4 = 7이다.
두번째 MathOperation = Multiply;은 마찬가지로 위 코드처럼 정적 메서드로 만들어진 Multiply를 가리리키고 있기에, 똑같이 값을 넣어 반환 받을 수 있게 된다. 따라서 MathOperation = Multiply;의 값은 7*5 = 35다
static void Main(string[] args)
{
Func<int, int, int> MathOperation;
MathOperation = Add;
Console.WriteLine(MathOperation(3, 4));
MathOperation = Multiply;
Console.WriteLine(MathOperation(7, 5));
}
내 답:
Func는 매개변수 두 가지를 받아서 세 번째에 있는 인수를 결과 값으로 내보내는 delegate의 일종입니다. Add와 Multiply 모두 매개변수 두 가지를 받아 결과값을 return하므로 바뀐 방식으로도 작동 합니다.
모범 답:
이 문장을 이해하기 위해선 Func 친구에 대해 이해해야한다. Func은 Function의 줄임말인데 앞에 두 함수를 매개변수로 받고 마지막에 오는 함수를 반환형으로 설정하는 키워드이다. 예시로 예를 들면 앞의 int 자료형 두개는 각각 매개변수의 값을 차례대로 저장하고 이를 return할 때 마지막에 오는 int를 통해 반환하게 된다. 따라서 앞의 첫번째 예시와 동일한 기능을 유지하기에 똑같이 동작하게 되고 값도 같다.
추가로 Func은 void가 아닌 반환형이 있을 때만 사용할 수 있다.
Ex: static int Add(int a, int b)
내 답:
위 코드에서 볼 수 있듯이 코드의 유연성과 재사용성이 향상된다고 생각합니다.
모범 답:
코드의 유연성 : 델리게이트를 사용하여 메서드를 동적으로 변경가능
코드의 재사용성 : 동일한 델리게이트 타입을 여러 메서드에서 호출할 수 있다.
유지 보수성 : 특정 로직을 캡슐화하고 분리하여 코드를 구조화시킬 수 있다.
다형성 : 다양한 메서드를 동일한 방식으로 호출 가능
콜백 메커니즘 구현 : 델리게이트를 사용하여 콜백 메서드를 쉽게 구현가능. 이벤트 처리나 비동기 작업에 유용.
익명 메서드 및 람다 표현식 사용 가능 : 익명 메서드나 람다 표현실을 활용하여 간결한 코드 작성 가능.
모범 답:
함수를 참조한다고 설명해주면 좋습니다. 비동기 처리를 위해서도 사용한다고 설명할 수 있습니다. 델리게이트나 이벤트를 미리 언급하는 것도 좋습니다. 특정 시점에 콜백을 사용한 경험이 있다면 그 사례를 간단히 언급해주시면 좋습니다.
콜백(callback)이란 다른 메서드가 완료된 후 호출되는 메서드를 의미한다. 주로 비동기 프로그래밍, 이벤트 처리, 또는 특정 조건이 충족되었을 때 실행되도록 하기 위해 사용한다.
콜백을 쉽게 이해하기 위해서는 동기, 비동기 프로그래밍에 대해 이해해 보아야 한다.
동기 프로그래밍 : 작업이 순차적으로 진행되며, 하나의 작업이 완료될 때까지 다음 작업이 시작되지 않음.
비동기 프로그래밍 : 작업이 시작도면 즉시 제어가 반환되어 다음 작업이 실행, 콜백 함수나 다른 메커니즘을 통해 결과를 처리 가능
콜백을 사용해본 경험으로는 유명한 Coroutine을 예시로 들 수 있다. 코루틴은 비동기 작업을 처리하는 가장 일반적인 방법인데, IEumerator를 반환하는 메서드를 구현하여 사용한다. yield 키워드를 사용하여 특정 조건이 충족될 때까지 실행을 일시 중지할 수도 있다. 이를 통해 매개변수로 시간를 받고 몬스터를 특정 시간동안 계속 생성하는 로직을 구현해 본적이 있다.
모범 답:
- 콜백과 함께 설명해주시면 좋습니다. 추가적으로 함수 포인터와 함께 설명할 수 있습니다.
- 대답하는 상황에 맞춰 타입 안정성과 멀티캐스트에 대한 언급을 해주면 더 좋습니다.
델리게이트(delegate)는 C#에서 메서드를 참조하는 형식을 정의하는데 사용된다. 델리게이트는 메서드의 시그니쳐(매개변수 및 반환 타입)를 기반으로 하고, 해당 시그니쳐와 일치하는 메서드를 가리킬 수 있다. 델리게이트는 형식 안전하며, 메서드를 매개변수로 전달하거나, 이벤트를 처리하거나, 런타임에 메서드를 동적으로 호출하는데 주로 사용한다.
public delegate int MyCallback(int a, int b);
using System;
public class Publisher
{
// 이벤트 선언
public event EventHandler MyEvent;
// 이벤트 발생시키는 메서드
public void RaiseEvent()
{
// 이벤트가 null이 아닌 경우에만 이벤트 발생
MyEvent?.Invoke(this, EventArgs.Empty);
}
}
public class Subscriber
{
public void Subscribe(Publisher publisher)
{
// 이벤트 구독
publisher.MyEvent += HandleEvent;
}
private void HandleEvent(object sender, EventArgs e)
{
Console.WriteLine("이벤트가 발생했습니다.");
}
}
class Program
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
// 구독자가 이벤트 구독
subscriber.Subscribe(publisher);
// 이벤트 발생
publisher.RaiseEvent();
}
}
모범 답:
델리게이트 기반이라는 점을 꼭 언급해주시면 좋습니다. 이벤트는 구독자 패턴을 통해 여러 메서드를 한 번에 호출할 수 있게 하며, 특정 조건에서 실행되는 이벤트 핸들러를 등록하고 호출하는 구조로 설명해주시면 좋습니다.
이벤트(event)는 C# 특정 상황이 발생했을 때 발생하는 신호이다. 이벤트는 주로 GUI 프로그래밍, 비동기 작업, 또는 특정 조건이 충족될 때 실행되는 동작을 처리하는 데 사용한다. 이벤트는 델리게이트를 기반으로 하며, 이벤트를 구독하고 발생시키는 방식으로 동작한다.
유니티 기준으로 아래의 예시처럼 사용할 수 있다.
public event Action onCallback; // 이벤트 선언
void Start()
{
onCallback += UseCallback; // 이벤트 등록
}
public void UseCallBack()
{
// 출력 내용
}
public void isEvent()
{
onCallback?.Invoke(); // 이벤트 호출
}
모범 답:
UnityEvent와 UnityAction 같은 델리게이트 및 이벤트를 언급해주시면 좋습니다. 이벤트 기반 게임 로직을 구현하는 데 사용되며, 이벤트 핸들링의 예시를 들어 설명해주시면 좋습니다.
Untiy에서는 UnityAction 및 UnityEvent를 주로 사용할 수 있다.
UnityAction은 인수가 없는 델리게이트이며, Unity의 이벤트 시스템에서 많이 사용된다.
UnityEvent는 인스펙터에서 설정할 수 있는 이벤트이다.
주로 Unity에서는 EventHandler를 주로 사용하게 된다.
플레이어가 데미지를 받을 때 여러 기능이 한번에 작동하도록 시스템을 만드려고 합니다.
상태 메시지가 출력되고, 피격 이펙트가 나오며, 피격 사운드가 재생되는 메서드가 구현되어 있는 상황입니다.
DisplayStatus
: 데미지 상태를 출력하는 메서드입니다.DisplayHitEffect
: 피격 이펙트를 표시하는 메서드PlayHitSound
: 피격 사운드를 재생하는 메서드1) TakeDamage 함수 내에서 플레이어가 데미지를 받을 때 이벤트를 발생(Publish)시키는 코드를 작성합니다.
2) DisplayAndSound 클래스의 생성자에서 이벤트 발생 시 호출될 메서드(DisplayStatus
, DisplayHitEffect
, PlayHitSound
)를 연결합니다.
⚠️주의!!!)
조건 : 데미지를 받는 로직을 처리하는 TakeDamage 메서드 안에서 DisplayStatus
, DisplayHitEffect
, PlayHitSound
를 직접 호출하지 않고 코드를 완성해봅시다.
using System;
namespace GameEventExample
{
// 이벤트 데이터를 담는 EventArgs 파생 클래스
public class PlayerDamagedEventArgs : EventArgs
{
public int Damage { get; set; }
}
// 플레이어 클래스
public class Player
{
public int HP { get; private set; } = 100;
// 플레이어가 데미지를 받을 때 발생하는 이벤트를 정의하세요.
public event EventHandler<PlayerDamagedEventArgs> PlayerDamaged;
// 플레이어가 데미지를 받는 메서드
public void TakeDamage(int damage)
{
HP -= damage;
PlayerDamagedEventArgs e = new PlayerDamagedEventArgs { Damage = damage };
// TODO: 이벤트가 등록되어 있는지 확인하고 이벤트를 발생
PlayerDamaged?.Invoke(this, e);
//
}
}
public class DisplayAndSound
{
public DisplayAndSound(Player player)
{
// TODO : 각각의 이벤트 핸들러를 등록하세요.
player.PlayerDamaged += DisplayStatus;
player.PlayerDamaged += DisplayHitEffect;
player.PlayerDamaged += PlayHitSound;
//
}
// 데미지 상태를 출력하는 메서드
void DisplayStatus(object sender, PlayerDamagedEventArgs e)
{
Player player = sender as Player;
Console.WriteLine($"Player took {e.Damage} damage!");
Console.WriteLine($"Remaining HP: {player.HP}");
}
// 피격 이펙트를 표시하는 메서드
void DisplayHitEffect(object sender, PlayerDamagedEventArgs e)
{
Console.WriteLine("Displaying hit effect...");
}
// 피격 사운드를 재생하는 메서드
void PlayHitSound(object sender, PlayerDamagedEventArgs e)
{
Console.WriteLine("Playing hit sound...");
}
}
class Program
{
static void Main(string[] args)
{
Player player = new Player();
DisplayAndSound displayAndSound = new DisplayAndSound(player);
// 플레이어가 데미지를 받아 이벤트를 발생
player.TakeDamage(20);
Console.WriteLine($"Player HP: {player.HP}");
}
}
}