IRONSOFTWAREHOME

Entendendo o delegado C#

Understanding C# Delegate

Tim Corey

1h 9m 11s

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; }
}

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:

  1. 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);
    • Este delegado especifica um método que retorna void e recebe um decimal como parâmetro.
  2. 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;
        }
    }
    C#
  3. 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}");
    }
    C#
  4. 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 });
        }
    }
    C#

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;
    }
}

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.

  1. 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);
    }
    C#
  2. 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;
        }
    }
    C#
  3. 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;
            }
        }
    }
    C#

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).

  1. 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);
    }
    C#
  2. 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);
    }
    C#
  3. 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);
        }
    }
    C#

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.

  1. 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 });
        }
    }
    C#
  2. Compreendendo a sintaxe :

    • A sintaxe do método anônimo usa o operador => (expressão lambda) para definir o corpo do método diretamente no lugar.
    • Não é necessário especificar o tipo de retorno ou o nome do método.

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

  1. 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
    }
}

Criando métodos para delegados

  1. 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);
    }
    C#
  2. SubtotalAlert :

    • Este método exibirá o subtotal em uma caixa de mensagem.
    private void SubtotalAlert(decimal subtotal)
    {
        MessageBox.Show($"The subtotal is {subtotal:C2}");
    }
    C#
  3. 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;
    }
    C#

Integrando os Delegados com o WinForms

  1. Utilizando Delegados no Evento de Clique de Botão :

    • O método messageBoxDemoButton_Click demonstra como passar os delegados para o método GenerateTotal e manipular 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}");
    }
    C#
  2. 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!

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!

Let's Stay in Touch!

Join our newsletter, you’ll get exclusive access on article updates. We value your privacy

Key in blue circle

Obtenha sua chave de avaliação gratuita de 30 dias instantaneamente.

Your trial license will be sent to your email address

Sem limitações. 100% desbloqueado. Sem cartão de crédito.

OR
bullet_checkedNão é necessário cartão de crédito nem criação de conta.Sem limitações. 100% desbloqueado. Sem cartão de crédito.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried Iron Suite
Agende sua consulta sem compromisso.
Preencha o formulário abaixo ou envie um e-mail para sales@ironsoftware.com
Os seus dados serão sempre mantidos em sigilo.
Aprovado por milhões de engenheiros em todo o mundo.
Logotipos dos clientes da Iron Software
Obtenha sua chave de avaliação gratuita de 30 dias instantaneamente.
Não é necessário cartão de crédito nem criação de conta.