Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
1시간 9분 11초
C#의 델리게이트는 강력한 기능이지만, 많은 개발자들이 이를 효과적으로 사용하는 방법을 잘 모릅니다. Tim Corey의 " C#의 델리게이트 - Action 및 Func를 포함한 실용적인 데모 " 비디오는 델리게이트가 무엇인지, 어떻게 사용하는지, 그리고 왜 유용한지에 대한 자세한 설명을 제공합니다.
이 글에서는 Tim의 전문적인 견해를 바탕으로 C#의 델리게이트에 대한 명확한 설명과 실제 적용 사례를 제공합니다. 이 강의에서는 쇼핑 카트 시스템에서의 활용 사례와 같이, 델리게이트를 통해 코드의 유연성과 효율성을 향상시키는 방법을 배우게 됩니다.
Tim은 C#에서 델리게이트의 개념과 그 강력함 및 다재다능함을 강조하며 소개합니다. 그는 시청자들에게 다소 위압적인 용어가 사용되더라도 대의원 제도의 기본 원칙은 간단하다고 확신시켜 줍니다. Tim은 대리자에 대한 오해를 풀고 함수 및 액션과 같은 특수 유형을 다루는 것을 목표로 합니다.
팀은 대리인 사용법을 설명하기 위해 데모 애플리케이션을 설정합니다. 이 솔루션에는 콘솔 UI, 데모 라이브러리 및 WinForm UI의 세 가지 프로젝트가 포함되어 있습니다. 초기에는 콘솔 UI와 데모 라이브러리에 초점을 맞출 것입니다.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleUI
{
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal():C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
}
}
public class ShoppingCartModel
{
public List<ProductModel> Items { get; set; } = new List<ProductModel>();
public decimal GenerateTotal()
{
decimal subtotal = Items.Sum(x => x.Price);
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
}
public class ProductModel
{
public string ItemName { get; set; }
public decimal Price { get; set; }
}Imports System
Imports System.Collections.Generic
Imports System.Linq
Namespace ConsoleUI
Class Program
Private Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal():C2}")
Console.ReadLine()
End Sub
Private Shared Sub PopulateCartWithDemoData()
cart.Items.Add(New ProductModel With {.ItemName = "Cereal", .Price = 3.63D})
cart.Items.Add(New ProductModel With {.ItemName = "Milk", .Price = 2.95D})
cart.Items.Add(New ProductModel With {.ItemName = "Strawberries", .Price = 7.51D})
cart.Items.Add(New ProductModel With {.ItemName = "Blueberries", .Price = 6.75D})
End Sub
End Class
End Namespace
Public Class ShoppingCartModel
Public Property Items As List(Of ProductModel) = New List(Of ProductModel)()
Public Function GenerateTotal() As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
If subtotal > 100 Then
Return subtotal * 0.80D
ElseIf subtotal > 50 Then
Return subtotal * 0.85D
ElseIf subtotal > 10 Then
Return subtotal * 0.90D
Else
Return subtotal
End If
End Function
End Class
Public Class ProductModel
Public Property ItemName As String
Public Property Price As Decimal
End Class팀은 데모 애플리케이션의 구조와 기능에 대해 설명합니다.
쇼핑 카트 모델 : 상품 목록(ProductModel)이 담긴 쇼핑 카트를 나타내며, 소계를 기준으로 할인을 적용한 총비용을 계산합니다.
제품 모델 : 이름과 가격 속성을 가진 개별 품목을 나타냅니다.
콘솔 애플리케이션 : 데모 데이터로 장바구니를 채우고, 총액을 계산하여 표시합니다.
Tim은 GenerateTotal 메서드의 할인 로직을 설명하면서 소계가 적용되는 할인을 결정하는 방식을 설명합니다.
팀은 시청자들이 계산 및 할인 논리를 이해한 후에야 참가자들을 소개할 수 있도록 중단점을 사용하여 설명합니다.
이 섹션에서 Tim Corey는 C#의 델리게이트 개념을 자세히 살펴보고, 작동 방식과 실제 코드 예제를 통해 사용법을 설명합니다.
팀은 델리게이트란 기본적으로 메서드를 매개변수로 전달하는 방법이라고 설명합니다. 변수나 속성을 전달하는 대신 메서드를 전달하면 더욱 유연하고 재사용 가능한 코드를 작성할 수 있습니다.
Tim은 위임자를 생성하고 사용하는 과정을 다음과 같이 설명합니다.
대리인을 정의하십시오 .
public delegate void MentionDiscount(decimal subtotal);Public Delegate Sub MentionDiscount(subtotal As Decimal)메서드에서 델리게이트 사용하기 :
public decimal GenerateTotal(MentionDiscount mentionDiscount)
{
decimal subtotal = Items.Sum(x => x.Price);
// Call a method passed as a delegate
mentionDiscount(subtotal);
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
델리게이트에 전달할 메서드 생성 :
private static void SubtotalAlert(decimal subtotal)
{
Console.WriteLine($"The subtotal is {subtotal:C2}");
}
GenerateTotal 메서드 호출 :
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(SubtotalAlert):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
}
팀은 위임 기능이 어떻게 작동하는지 보여주기 위해 애플리케이션을 실행합니다. 콘솔 출력에는 장바구니의 소계와 총액이 표시되며, 이는 SubtotalAlert 메서드가 델리게이트를 통해 성공적으로 전달되고 실행되었음을 나타냅니다.

이어서 Tim Corey는 C#에서 func 및 action 델리게이트의 사용법을 살펴봅니다. 이는 마이크로소프트에서 제네릭과의 대리자 사용을 간소화하기 위해 제공하는 특수한 유형의 대리자입니다.
Tim은 GenerateTotal 메서드에 할인 로직이 하드코딩되어 있는 일반적인 문제점을 지적합니다. 이 접근 방식은 유연성이 부족하고 할인 규칙이 변경될 때마다 코드 변경, 재컴파일 및 재배포가 필요합니다.
public decimal GenerateTotal()
{
decimal subtotal = Items.Sum(x => x.Price);
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}Public Function GenerateTotal() As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
If subtotal > 100 Then
Return subtotal * 0.80D
ElseIf subtotal > 50 Then
Return subtotal * 0.85D
ElseIf subtotal > 10 Then
Return subtotal * 0.90D
Else
Return subtotal
End If
End FunctionTim은 하드코딩된 할인 문제를 해결하기 위해 func delegate를 도입합니다. func 델리게이트는 반환 타입과 최대 16개의 입력 매개변수를 갖는 메서드 시그니처를 나타내는 제네릭 델리게이트입니다.
함수 델리게이트 정의 :
public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal)
{
decimal subtotal = Items.Sum(x => x.Price);
MentionDiscount(subtotal);
return calculateDiscountedTotal(Items, subtotal);
}
할인 계산 방법 생성 :
private static decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
메서드를 함수 델리게이트에 전달하기 :
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(CalculateLevelDiscount):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
private static decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
}
팀은 수정된 애플리케이션을 시연하며, 제공된 로직에 따라 할인율을 동적으로 계산하고 올바르게 작동하는 것을 보여줍니다.

Tim은 사용자 정의 델리게이트와 함수 델리게이트를 비교합니다.
위임 : 서명에 대한 명확한 정의가 필요하며, 명확한 문서화 및 구조를 제공해야 합니다.
함수형 표기법 : 더 간결하지만 입력 및 출력 유형을 매번 지정해야 하므로 명확성이 떨어질 수 있습니다.
두 접근 방식 모두 유연성을 제공하지만, 선택은 특정 사용 사례와 애플리케이션의 복잡성에 따라 달라집니다.
팀 코리는 대리인 활용에 대한 일반적인 질문, 즉 모든 업무가 다른 곳에서 처리되는 것처럼 보인다면 왜 대리인을 두어야 하는지에 대해 답변합니다.
팀은 델리게이트의 목적은 코드에 유연성과 확장성을 제공하는 것이라고 설명합니다. ShoppingCartModel 클래스의 GenerateTotal 메서드는 할인 계산 외에도 다른 작업을 수행할 수 있습니다. 또한 재고 확인, 장바구니 내용 검증 또는 기타 비즈니스 로직과 같은 작업도 처리할 수 있습니다. 델리게이트를 사용하면 핵심 메서드를 변경하지 않고도 고유한 작업이나 사용자 지정 동작을 위한 특정 메서드를 전달할 수 있습니다. 이렇게 하면 코드가 더욱 모듈화되고 유지 관리가 쉬워집니다.
위임 기능은 다음과 같은 상황에서 특히 유용합니다.
Tim은 C#의 또 다른 특별한 유형의 델리게이트인 Action 델리게이트를 소개합니다. Action 델리게이트는 Func와 유사하지만 값을 반환하지 않습니다(즉, void를 반환합니다).
액션 델리게이트 생성 :
public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal, Action<string> tellUserWeAreDiscounting)
{
decimal subtotal = Items.Sum(x => x.Price);
MentionSubtotal(subtotal);
tellUserWeAreDiscounting("We are applying your discount.");
return calculateDiscountedTotal(Items, subtotal);
}
알림 메서드 생성 :
private static void AlertUser(string message)
{
Console.WriteLine(message);
}
액션 델리게이트에 메서드 전달하기 :
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(CalculateLevelDiscount, AlertUser):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
private static decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (subtotal > 100)
{
return subtotal * 0.80M;
}
else if (subtotal > 50)
{
return subtotal * 0.85M;
}
else if (subtotal > 10)
{
return subtotal * 0.90M;
}
else
{
return subtotal;
}
}
private static void AlertUser(string message)
{
Console.WriteLine(message);
}
}
Tim은 익명 메서드를 사용하는 방법을 보여주는데, 이를 통해 메서드에 이름을 지정하지 않고도 실행 중에 메서드를 정의할 수 있습니다.
익명 메서드 정의 :
class Program
{
static ShoppingCartModel cart = new ShoppingCartModel();
static void Main(string[] args)
{
PopulateCartWithDemoData();
Console.WriteLine($"The total for the cart is {cart.GenerateTotal((items, subtotal) =>
{
if (subtotal > 100) return subtotal * 0.80M;
else if (subtotal > 50) return subtotal * 0.85M;
else if (subtotal > 10) return subtotal * 0.90M;
else return subtotal;
},
(message) => Console.WriteLine(message)):C2}");
Console.ReadLine();
}
private static void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
}
구문 이해하기 :
=> 연산자(람다 표현식)를 사용합니다.Func, Action 및 익명 메서드를 포함한 델리게이트를 사용하면 개발자는 더욱 동적이고 모듈화된 코드를 작성하여 유연하고 재사용 가능한 구성 요소를 만들 수 있습니다.
이 부분에서 Tim Corey는 WinForms 애플리케이션에 델리게이트를 적용하는 방법을 보여줌으로써 델리게이트의 강력한 기능을 시연합니다. 이는 대리인이 다양한 사용자 인터페이스(UI) 환경에서 서로 다른 동작을 어떻게 구현할 수 있는지를 보여줍니다.
버튼 두 개가 있는 WinForm UI :
양식에는 두 개의 버튼이 있습니다. 하나는 메시지 상자를 보여주는 버튼이고, 다른 하나는 텍스트 상자를 보여주는 버튼입니다.
ShoppingCartModel과 데모 데이터를 채워 넣는 메서드도 포함되어 있습니다.
public partial class Dashboard : Form
{
ShoppingCartModel cart = new ShoppingCartModel();
public Dashboard()
{
InitializeComponent();
PopulateCartWithDemoData();
}
private void PopulateCartWithDemoData()
{
cart.Items.Add(new ProductModel { ItemName = "Cereal", Price = 3.63M });
cart.Items.Add(new ProductModel { ItemName = "Milk", Price = 2.95M });
cart.Items.Add(new ProductModel { ItemName = "Strawberries", Price = 7.51M });
cart.Items.Add(new ProductModel { ItemName = "Blueberries", Price = 6.75M });
}
private void messageBoxDemoButton_Click(object sender, EventArgs e)
{
decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert);
MessageBox.Show($"The total is {total:C2}");
}
private void textBoxDemoButton_Click(object sender, EventArgs e)
{
// Code for TextBox demo will go here
}
}Public Partial Class Dashboard
Inherits Form
Private cart As New ShoppingCartModel()
Public Sub New()
InitializeComponent()
PopulateCartWithDemoData()
End Sub
Private Sub PopulateCartWithDemoData()
cart.Items.Add(New ProductModel With {.ItemName = "Cereal", .Price = 3.63D})
cart.Items.Add(New ProductModel With {.ItemName = "Milk", .Price = 2.95D})
cart.Items.Add(New ProductModel With {.ItemName = "Strawberries", .Price = 7.51D})
cart.Items.Add(New ProductModel With {.ItemName = "Blueberries", .Price = 6.75D})
End Sub
Private Sub messageBoxDemoButton_Click(sender As Object, e As EventArgs) Handles messageBoxDemoButton.Click
Dim total As Decimal = cart.GenerateTotal(AddressOf SubtotalAlert, AddressOf CalculateLevelDiscount, AddressOf PrintOutDiscountAlert)
MessageBox.Show($"The total is {total:C2}")
End Sub
Private Sub textBoxDemoButton_Click(sender As Object, e As EventArgs) Handles textBoxDemoButton.Click
' Code for TextBox demo will go here
End Sub
End ClassPrintOutDiscountAlert :
private void PrintOutDiscountAlert(string message)
{
MessageBox.Show(message);
}
소계알림 :
private void SubtotalAlert(decimal subtotal)
{
MessageBox.Show($"The subtotal is {subtotal:C2}");
}
레벨 할인 계산 :
private decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (items.Count > 3)
{
return subtotal - 3M;
}
return subtotal - items.Count;
}
버튼 클릭 이벤트에서 델리게이트 사용하기 :
messageBoxDemoButton_Click 메서드는 대리자를 GenerateTotal 메서드에 전달하고 메시지 상자를 사용하여 결과를 처리하는 방법을 보여줍니다.private void messageBoxDemoButton_Click(object sender, EventArgs e)
{
decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert);
MessageBox.Show($"The total is {total:C2}");
}
애플리케이션 실행 :

팀 코리는 C#의 델리게이트에 대해 명확하게 설명하며, 기초부터 고급 사용법, 그리고 쇼핑 카트에서 델리게이트를 사용하는 것과 같은 실용적인 예제까지 다룹니다. 그는 델리게이트를 통해 Func, Action 및 익명 메서드를 포함한 유연하고 재사용 가능한 코드를 작성하는 방법을 보여줍니다. 전체 영상을 시청하여 프로젝트에 대리인 제도를 효과적으로 적용하는 방법을 알아보세요!
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy