Entendendo o delegado C#
Os delegates em C# são um recurso poderoso, mas muitos desenvolvedores não estão familiarizados com seu uso eficaz. O vídeo de Tim Corey sobre " Delegates em C# - Uma demonstração prática, incluindo Action e Func " oferece uma explicação completa do que são delegates, como usá-los e por que são úteis.
Este artigo fornecerá a você as informações especializadas de Tim sobre delegates em C#, oferecendo uma explicação clara de seu uso e aplicações práticas. Você aprenderá como os delegates podem aumentar a flexibilidade e a eficiência do seu código, com exemplos como seu uso em um sistema de carrinho de compras.
Introdução
Tim apresenta o conceito de delegates, destacando seu poder e versatilidade em C#. Ele garante aos espectadores que, apesar de alguma terminologia intimidante, a base dos delegados é simples. Tim pretende desmistificar os delegados e abordar tipos especiais como func e action.
Demonstração do Aplicativo - Passo a Passo
Tim configura um aplicativo de demonstração para ilustrar o uso de delegados. A solução contém três projetos: uma interface de usuário de console, uma biblioteca de demonstração e uma interface de usuário WinForm. Inicialmente, o foco será na interface do usuário do console e na biblioteca de demonstrações.
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; }
}
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; }
}
Tim explica a estrutura e a funcionalidade do aplicativo de demonstração:
-
Modelo de Carrinho de Compras : Representa o carrinho de compras com uma lista de itens (ProductModel) e calcula o custo total com descontos com base no subtotal.
-
Modelo de produto : Representa itens individuais com propriedades de nome e preço.
- Aplicativo de console : Preenche o carrinho com dados de demonstração, calcula o total e o exibe.
Entendendo os descontos
Tim explica a lógica de desconto no método GenerateTotal, detalhando como o subtotal determina o desconto aplicado:
- 20% de desconto para subtotais acima de $100.
- 15% de desconto para subtotais acima de $50.
- 10% de desconto para subtotais acima de $10.
- Não há desconto para subtotais de $10 ou menos.
Tim utiliza um ponto de interrupção para demonstrar a lógica de cálculo e desconto, garantindo que os espectadores compreendam os fundamentos antes de apresentá-los aos participantes.
Explicando e criando um delegado
Nesta seção, Tim Corey explora o conceito de delegates em C#, explicando como funcionam e demonstrando seu uso com exemplos práticos de código.
O que é um Delegado?
Tim explica que um delegate é essencialmente uma forma de passar métodos como parâmetros. Em vez de passar uma variável ou uma propriedade, você passa um método, o que permite um código mais flexível e reutilizável.
Criando e usando um delegado
Eis como Tim explica o processo de criação e utilização de um delegado:
-
Defina o Delegado :
- O delegado é definido no início da classe, especificando o tipo de retorno e os tipos de parâmetros.
public delegate void MentionDiscount(decimal subtotal);public delegate void MentionDiscount(decimal subtotal);- Este delegado especifica um método que retorna void e recebe um decimal como parâmetro.
-
Utilizando o Delegado em um Método :
- O delegado é usado como parâmetro no método GenerateTotal da classe ShoppingCartModel.
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; } }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; } } -
Criando um método para passar para o delegado :
- Um método que corresponde à assinatura do delegado é criado na classe Program.
private static void SubtotalAlert(decimal subtotal) { Console.WriteLine($"The subtotal is {subtotal:C2}"); }private static void SubtotalAlert(decimal subtotal) { Console.WriteLine($"The subtotal is {subtotal:C2}"); } -
Chamando o método GenerateTotal :
- O método é passado para o método GenerateTotal através do delegado.
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 }); } }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 }); } }
Executando o aplicativo
Tim executa o aplicativo para demonstrar como o delegado funciona. A saída do console mostra o subtotal e o total do carrinho, indicando que o método SubtotalAlert foi passado e executado com sucesso por meio do delegado.

Função e Ação: Problemas que você pode resolver com delegados
Tim Corey então explora o uso de funções e delegados de ação em C#. Esses são tipos especiais de delegados fornecidos pela Microsoft para simplificar o uso de delegados com genéricos.
Identificando o problema
Tim destaca um problema comum: a lógica de desconto codificada diretamente no método GenerateTotal. Essa abordagem é inflexível e exige alterações de código, recompilação e reimplementação sempre que as regras de desconto mudam.
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 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;
}
}
Apresentando o Func Delegate
Tim apresenta o delegado func para resolver o problema do desconto fixo no código. O delegado func é um delegado genérico que representa a assinatura de um método com um tipo de retorno e até 16 parâmetros de entrada.
-
Definindo o Delegado Func :
- O delegado de função é usado no método GenerateTotal para lidar com cálculos de desconto dinamicamente.
public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal) { decimal subtotal = Items.Sum(x => x.Price); MentionDiscount(subtotal); return calculateDiscountedTotal(Items, subtotal); }public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal) { decimal subtotal = Items.Sum(x => x.Price); MentionDiscount(subtotal); return calculateDiscountedTotal(Items, subtotal); } -
Criação do método de cálculo de desconto :
- Um método que corresponde à assinatura do delegado da função é criado na classe Program.
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 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; } } -
Passando o método para o delegado da função :
- O método CalculateLevelDiscount é passado para o método GenerateTotal através do delegado da função.
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; } } }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; } } }
Executando o aplicativo
Tim demonstra a aplicação modificada, mostrando que ela funciona corretamente e calcula dinamicamente o desconto com base na lógica fornecida.

Diferenças entre Delegar e Funcionar
Tim compara o delegado personalizado e o delegado funcional:
-
Delegado : Requer definição explícita da assinatura, fornecendo documentação e estrutura claras.
- Func : Mais conciso, mas exige a especificação dos tipos de entrada e saída a cada vez, o que pode ser menos claro.
Ambas as abordagens oferecem flexibilidade, mas a escolha depende do caso de uso específico e da complexidade da aplicação.
Por que usar delegados se todo o trabalho é feito em outro lugar?
Tim Corey aborda uma pergunta comum sobre o uso de delegados: Por que ter um delegado se todo o trabalho parece ser feito em outro lugar?
Tim explica que o objetivo dos delegates é proporcionar flexibilidade e extensibilidade ao código. O método GenerateTotal na classe ShoppingCartModel pode fazer mais do que apenas calcular descontos. Também pode lidar com tarefas como verificar a disponibilidade de estoque, validar o conteúdo do carrinho ou outras lógicas de negócios. Os delegates permitem que você passe métodos específicos para tarefas únicas ou comportamentos personalizados sem alterar o método principal. Isso torna o código mais modular e mais fácil de manter.
Os delegados são especialmente úteis em cenários onde você deseja:
- Aplicar regras de negócio ou lógica diferentes de forma dinâmica.
- Mantenha o método principal genérico e reutilizável.
- Implementar comportamentos personalizados para casos específicos sem modificar o método principal.
Delegado de Ação: Criando e Explicando
Tim apresenta o delegado Action, outro tipo especial de delegado em C#. O delegado Action é semelhante ao Func, mas não retorna um valor (ou seja, retorna void).
-
Criando o Delegado de Ação :
- Defina o delegado Action no método GenerateTotal para lidar com alertas ou mensagens.
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); }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); } -
Criando o método de alerta :
- Defina um método que corresponda à assinatura do delegado da ação.
private static void AlertUser(string message) { Console.WriteLine(message); }private static void AlertUser(string message) { Console.WriteLine(message); } -
Passando o método para o delegado de ação :
- Passe o método AlertUser para o método GenerateTotal através do delegado Action.
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); } }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); } }
Criação de Métodos Anônimos: Delegado Anônimo
Tim mostra como usar métodos anônimos, permitindo que você defina métodos dinamicamente sem precisar nomeá-los.
-
Definindo Métodos Anônimos :
Em vez de criar métodos nomeados, você pode definir os métodos diretamente onde eles são necessários.
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 }); } }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 }); } } -
Compreendendo a sintaxe :
- A sintaxe de método anônimo usa o operador
=>(expressão lambda) para definir o corpo do método diretamente em linha. - Não é necessário especificar o tipo de retorno ou o nome do método.
- A sintaxe de método anônimo usa o operador
Ao utilizar delegates, incluindo Func, Action e métodos anônimos, os desenvolvedores podem criar um código mais dinâmico e modular, permitindo componentes flexíveis e reutilizáveis.
Utilizando Delegados em Outros Projetos: WinForms
Neste segmento, Tim Corey demonstra o poder dos delegates, estendendo seu uso a um aplicativo WinForms. Isso destaca como os delegados podem facilitar diferentes comportamentos em vários contextos de interface do usuário (IU).
Configurando o aplicativo WinForms
-
Interface de usuário WinForm com dois botões :
-
O formulário possui dois botões: um para exibir caixas de mensagem e outro para exibir caixas de texto.
- O modelo ShoppingCartModel e um método para preenchê-lo com dados de demonstração também estão incluídos.
-
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 : 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
}
}
Criando métodos para delegados
-
PrintOutDiscountAlert :
- Este método será usado para exibir um alerta com as informações sobre o desconto.
private void PrintOutDiscountAlert(string message) { MessageBox.Show(message); }private void PrintOutDiscountAlert(string message) { MessageBox.Show(message); } -
SubtotalAlert :
- Este método exibirá o subtotal em uma caixa de mensagem.
private void SubtotalAlert(decimal subtotal) { MessageBox.Show($"The subtotal is {subtotal:C2}"); }private void SubtotalAlert(decimal subtotal) { MessageBox.Show($"The subtotal is {subtotal:C2}"); } -
CalcularDescontoPorNível :
- Este método calculará o desconto com base no número de itens no carrinho.
private decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal) { if (items.Count > 3) { return subtotal - 3M; } return subtotal - items.Count; }private decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal) { if (items.Count > 3) { return subtotal - 3M; } return subtotal - items.Count; }
Integrando os Delegados com o WinForms
-
Utilizando Delegados no Evento de Clique de Botão :
- O método
messageBoxDemoButton_Clickdemonstra como passar os delegados para o método GenerateTotal e lidar com os resultados usando caixas de mensagem.
private void messageBoxDemoButton_Click(object sender, EventArgs e) { decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert); MessageBox.Show($"The total is {total:C2}"); }private void messageBoxDemoButton_Click(object sender, EventArgs e) { decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert); MessageBox.Show($"The total is {total:C2}"); } - O método
-
Executando o aplicativo :
- Ao clicar no botão, o aplicativo WinForms exibe o subtotal e o total usando caixas de mensagem, demonstrando a flexibilidade dos delegates.

Conclusão
Tim Corey explica os delegates em C# de forma clara, abordando os conceitos básicos, o uso avançado e exemplos práticos, como a utilização de delegates em um carrinho de compras. Ele demonstra como os delegates permitem um código flexível e reutilizável, incluindo Func, Action e métodos anônimos. Assista ao vídeo completo para aprender como aplicar delegados de forma eficaz em seus projetos!
