학습
C# 델리게이트와 이벤트
C# 델리게이트와 이벤트 — 중급
델리게이트와 이벤트
1. 도입 (왜 배워야 하는가)
C#에서 델리게이트와 이벤트는 사건 기반 프로그래밍의 핵심 요소입니다. 이들을 잘 이해하면 사용자 인터페이스(UI)나 비동기 프로그래밍 등에서 발생하는 다양한 사건을 효과적으로 처리할 수 있습니다. 예를 들어, 버튼 클릭, 데이터 변경 등의 사건을 처리하는 데 필수적입니다.
만약 델리게이트와 이벤트를 모른다면, 다양한 사용자 입력이나 다른 객체와의 상호작용을 수동으로 처리해야 하므로 코드가 복잡해지고 유지보수가 어려워집니다. 이로 인해 실무에서 더 많은 시간과 비용이 소요될 수 있습니다.
2. 핵심 개념 설명
델리게이트
- 델리게이트는 메서드에 대한 참조를 저장할 수 있는 타입입니다. 즉, 특정 메서드를 호출할 수 있는 "포인터"와 같습니다.
- 비유: 델리게이트는 레스토랑에서 주문서를 작성하는 것과 비슷합니다. 고객이 요리를 주문하면, 주방이 해당 요리를 만들어내는 것처럼, 델리게이트는 특정 메서드를 호출합니다.
- 이벤트는 델리게이트를 기반으로 하며, 특정 사건이 발생했을 때 통지하는 메커니즘입니다. 다른 객체가 이 사건에 반응할 수 있도록 합니다.
- 비유: 이벤트는 파티 초대장과 같습니다. 초대장을 받은 사람들은 파티에 참석할 수 있지만, 초대장을 받은 사람은 초대장을 보낸 사람의 요청에 응답하는 것입니다.
이벤트
| 용어 | 설명 |
|---|---|
| 델리게이트 | 메서드에 대한 참조를 저장하는 타입 |
| 이벤트 | 델리게이트를 기반으로 한 사건 통지 메커니즘 |
3. 기본 코드 예제
델리게이트와 이벤트의 기본적인 사용법을 보여주는 예제입니다.
using System;
public delegate void Notify(); // 델리게이트 정의
public class Process
{
public event Notify ProcessCompleted; // 이벤트 정의
public void StartProcess()
{
Console.WriteLine("프로세스 시작...");
// 프로세스 작업 수행 (여기서는 단순 출력으로 대체)
System.Threading.Thread.Sleep(2000); // 2초 대기
OnProcessCompleted(); // 이벤트 호출
}
protected virtual void OnProcessCompleted()
{
ProcessCompleted?.Invoke(); // 이벤트 발생
}
}
public class Program
{
public static void Main(string[] args)
{
Process process = new Process();
process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!"); // 이벤트 구독
process.StartProcess(); // 프로세스 시작
}
}
실행 결과:
프로세스 시작...
프로세스 완료!
코드 한 줄씩 동작 설명:
public delegate void Notify();:Notify라는 이름의 델리게이트를 정의합니다. 반환 값이 없고 인수가 없습니다.public event Notify ProcessCompleted;:ProcessCompleted라는 이름의 이벤트를 정의합니다. 이 이벤트는Notify델리게이트를 사용합니다.public void StartProcess(): 프로세스를 시작하는 메서드입니다.System.Threading.Thread.Sleep(2000);: 2초 동안 대기하여 프로세스 작업을 시뮬레이션합니다.OnProcessCompleted();: 프로세스가 완료되었음을 나타내는 이벤트를 호출합니다.protected virtual void OnProcessCompleted(): 이벤트를 발생시키는 메서드입니다. 구독된 메서드를 호출합니다.ProcessCompleted?.Invoke();: 이벤트가 구독되어 있으면 호출합니다.process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!");:ProcessCompleted이벤트에 대한 구독을 설정합니다.process.StartProcess();: 프로세스를 시작합니다.- 잘못된 코드:
- 올바른 코드:
- 잘못된 코드:
- 올바른 코드:
- 델리게이트는 메서드에 대한 참조를 저장할 수 있는 타입이며, 이벤트는 델리게이트를 기반으로 한 사건 통지 메커니즘입니다.
- 델리게이트와 이벤트는 사용자 인터페이스 및 비동기 프로그래밍에서 사건 기반 처리에 매우 유용합니다.
- 델리게이트와 이벤트를 적절히 활용하면 코드의 가독성과 유지보수성을 높일 수 있습니다.
- LINQ (Language Integrated Query) : 데이터 처리 및 쿼리 작성
- 비동기 프로그래밍 (async/await) : 더 나은 비동기 흐름 제어
- 디자인 패턴 (Observer, Command 패턴 등) : 소프트웨어 설계에서의 다양한 패턴 적용.
4. 실전 활용 예제
예제 1: 쇼핑몰 장바구니 구현
쇼핑몰에서 장바구니에 상품을 추가할 때, 장바구니의 총합을 업데이트하는 이벤트를 사용할 수 있습니다.
using System;
using System.Collections.Generic;
public delegate void CartUpdatedEventHandler(decimal total);
public class ShoppingCart
{
public event CartUpdatedEventHandler CartUpdated;
private List<decimal> items = new List<decimal>();
public void AddItem(decimal price)
{
items.Add(price);
OnCartUpdated(CalculateTotal());
}
private decimal CalculateTotal()
{
decimal total = 0;
foreach (var item in items)
{
total += item;
}
return total;
}
protected virtual void OnCartUpdated(decimal total)
{
CartUpdated?.Invoke(total);
}
}
public class Program
{
public static void Main(string[] args)
{
ShoppingCart cart = new ShoppingCart();
cart.CartUpdated += (total) => Console.WriteLine($"장바구니 총합: {total:C}"); // 이벤트 구독
cart.AddItem(10.99m);
cart.AddItem(5.49m);
}
}
상황 설명: 사용자가 장바구니에 상품을 추가할 때마다, 장바구니의 총합이 업데이트되고 사용자에게 알림이 전송됩니다.
예제 2: 비동기 처리
비동기 작업이 완료되었을 때 이벤트를 사용하는 예제입니다.
using System;
using System.Threading.Tasks;
public class AsyncProcess
{
public event Action ProcessCompleted;
public async void StartAsyncProcess()
{
Console.WriteLine("비동기 프로세스 시작...");
await Task.Delay(2000); // 2초 대기
OnProcessCompleted();
}
protected virtual void OnProcessCompleted()
{
ProcessCompleted?.Invoke();
}
}
public class Program
{
public static void Main(string[] args)
{
AsyncProcess asyncProcess = new AsyncProcess();
asyncProcess.ProcessCompleted += () => Console.WriteLine("비동기 프로세스 완료!");
asyncProcess.StartAsyncProcess();
Console.ReadLine(); // 프로그램 종료 방지
}
}
상황 설명: 비동기 작업이 완료되면, 해당 작업이 완료되었음을 알리기 위해 이벤트를 사용합니다.
5. 흔한 실수와 주의사항
실수 1: 이벤트를 구독하지 않음
Process process = new Process();
process.StartProcess(); // 이벤트 구독 없음
Process process = new Process();
process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!");
process.StartProcess();
실수 2: 이벤트 핸들러 메서드에 잘못된 형식 사용
process.ProcessCompleted += (int total) => Console.WriteLine($"총합: {total}"); // 잘못된 형식
process.ProcessCompleted += () => Console.WriteLine("프로세스 완료!"); // 올바른 형식