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
1h 9m 11s
Delegaty w C# to potężna cecha, a jednak wielu programistów nie jest zaznajomionych z ich efektywnym użyciem. Film Tima Coreya o "Delegaty w C# - praktyczna demonstracja, w tym Action i Func" dostarcza dokładnego wyjaśnienia, czym są delegaty, jak ich używać i dlaczego są użyteczne.
Ten artykuł dostarczy ci eksperckich spostrzeżeń Tima na temat delegatów w C#, oferując jasne wyjaśnienie ich użycia i praktycznych zastosowań. Nauczysz się, jak delegaty mogą zwiększyć elastyczność i wydajność twojego kodu, z przykładami użycia w systemie koszyka zakupowego.
Tim wprowadza pojęcie delegatów, podkreślając ich moc i wszechstronność w C#. Zapewnia widzów, że pomimo niektórych przerażających terminologii, podstawa delegatów jest prosta. Tim dąży do demistyfikacji delegatów i omawia specjalne typy, takie jak func i action.
Tim tworzy aplikację demo, aby zilustrować użycie delegatów. Rozwiązanie zawiera trzy projekty: Konsolowe UI, Bibliotekę Demo i WinForm UI. Początkowo skupienie się jest na Konsolowym UI i Bibliotece Demo.
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 ClassTim wyjaśnia strukturę i funkcjonalność aplikacji demo:
Model Koszyka Zakupowego: Reprezentuje koszyk zakupowy z listą przedmiotów (ProductModel) i oblicza całkowity koszt z rabatami na podstawie sumy częściowej.
Model Produktu: Reprezentuje pojedyncze przedmioty z nazwą i ceną jako właściwościami.
Aplikacja Konsolowa: Wypełnia koszyk danymi demo, oblicza całkowitą wartość i wyświetla ją.
Tim przechodzi przez logikę rabatów w metodzie GenerateTotal, wyjaśniając, jak suma częściowa determinuje zastosowany rabat:
Tim używa punktu kontrolnego, aby pokazać logikę obliczeń i rabatów, zapewniając zrozumienie podstaw przed wprowadzeniem delegatów.
W tej sekcji Tim Corey zagłębia się w koncepcję delegatów w C#, wyjaśniając, jak działają i pokazując ich użycie na praktycznych przykładach kodu.
Tim wyjaśnia, że delegat to zasadniczo sposób na przekazywanie metod jako parametrów. Zamiast przekazywać zmienną lub właściwość, przekazujesz metodę, co pozwala na bardziej elastyczny i wielokrotnego użytku kod.
Oto jak Tim prezentuje proces tworzenia i użycia delegata:
Delegat jest definiowany na początku klasy, określając typ zwracany i typy parametrów.
public delegate void MentionDiscount(decimal subtotal);Public Delegate Sub MentionDiscount(subtotal As Decimal)Delegat jest używany jako parametr w metodzie GenerateTotal klasy 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;
}
}
Metoda pasująca do podpisu delegata jest tworzona w klasie Program.
private static void SubtotalAlert(decimal subtotal)
{
Console.WriteLine($"The subtotal is {subtotal:C2}");
}
Metoda jest przekazywana do metody GenerateTotal za pomocą delegata.
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 });
}
}
Tim uruchamia aplikację, aby pokazać, jak działa delegat. Output konsoli pokazuje sumę częściową i całkowitą dla koszyka, wskazując, że metoda SubtotalAlert została pomyślnie przekazana i wykonana za pomocą delegata.

Tim Corey następnie bada użycie func i action delegatów w C#. Są to specjalne typy delegatów dostarczone przez Microsoft, aby uprościć użycie delegatów z generykami.
Tim podkreśla powszechny problem: zaszyta na stałe logika rabatów w metodzie GenerateTotal. To podejście jest nieelastyczne i wymaga zmian w kodzie, rekompilacji i ponownego wdrożenia za każdym razem, gdy zmieniają się zasady rabatów.
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 wprowadza delegata func, aby rozwiązać problem zaszytej na stałe logiki rabatów. Delegat func to generyczny delegat, który reprezentuje podpis metody z typem zwracanym i do 16 parametrami wejściowymi.
Delegat func jest używany w metodzie GenerateTotal, aby dynamicznie obsługiwać obliczenia rabatów.
public decimal GenerateTotal(Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal)
{
decimal subtotal = Items.Sum(x => x.Price);
MentionDiscount(subtotal);
return calculateDiscountedTotal(Items, subtotal);
}
Metoda pasująca do podpisu delegata func jest tworzona w klasie 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;
}
}
Metoda CalculateLevelDiscount jest przekazywana do metody GenerateTotal za pomocą delegata func.
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 demonstruje zmodyfikowaną aplikację, pokazując, że działa poprawnie i dynamicznie oblicza rabat na podstawie dostarczonej logiki.

Tim porównuje delegat niestandardowy i delegat func:
Delegat: Wymaga wyraźnego zdefiniowania podpisu, co zapewnia jasną dokumentację i strukturę.
Func: Bardziej zwięzły, ale wymaga każdorazowego określenia typów wejściowych i wyjściowych, co może być mniej jasne.
Oba podejścia oferują elastyczność, ale wybór zależy od konkretnego przypadku użycia i złożoności aplikacji.
Tim Corey porusza powszechne pytanie dotyczące użycia delegatów: Dlaczego mieć delegat, jeśli cała praca wydaje się być gdzie indziej?
Tim wyjaśnia, że celem delegatów jest zapewnienie elastyczności i rozciągliwości kodu. Metoda GenerateTotal w klasie ShoppingCartModel może robić więcej niż tylko obliczać rabaty. Może również obsługiwać zadania takie jak sprawdzanie dostępności zapasów, walidacja zawartości koszyka lub inna logika biznesowa. Delegaty pozwalają na przekazywanie konkretnych metod do unikalnych zadań lub niestandardowego zachowania bez zmiany głównej metody. To sprawia, że kod jest bardziej modułowy i łatwiejszy do utrzymania.
Delegaty są szczególnie użyteczne w scenariuszach, gdy chcesz:
Tim wprowadza delegata Action, kolejny specjalny typ delegata w C#. Delegat Action jest podobny do Func, ale nie zwraca żadnej wartości (czyli zwraca void).
Zdefiniuj delegata Action w metodzie GenerateTotal, aby obsługiwać alerty lub komunikaty.
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);
}
Zdefiniuj metodę, aby pasowała do podpisu delegata Action.
private static void AlertUser(string message)
{
Console.WriteLine(message);
}
Przekaż metodę AlertUser do metody GenerateTotal za pomocą delegata 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);
}
}
Tim pokazuje, jak używać anonimowych metod, pozwalając na definiowanie metod na bieżąco bez ich nazywania.
Zamiast tworzyć nazwane metody, możesz definiować metody bezpośrednio tam, gdzie są potrzebne.
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 });
}
}
Zrozumienie Składni:
=> (wyrażenie lambda) do zdefiniowania ciała metody bezpośrednio w linii.Dzięki użyciu delegatów, w tym Func, Action i anonimowych metod, deweloperzy mogą tworzyć bardziej dynamiczny i modułowy kod, pozwalając na elastyczne i wielorazowe komponenty.
W tym segmencie Tim Corey demonstruje siłę delegatów, rozszerzając ich użycie na aplikację WinForms. To podkreśla, jak delegaty mogą ułatwić różne zachowania w różnych kontekstach interfejsu użytkownika (UI).
Forma ma dwa przyciski: jeden do demonstrowania okienek komunikatów i jeden do demonstrowania pól tekstowych.
ShoppingCartModel i metoda do jego wypełnienia danymi demo są również zawarte.
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 ClassTa metoda będzie używana do pokazywania alertu z informacjami o rabacie.
private void PrintOutDiscountAlert(string message)
{
MessageBox.Show(message);
}
Ta metoda wyświetli sumę częściową w oknie komunikatu.
private void SubtotalAlert(decimal subtotal)
{
MessageBox.Show($"The subtotal is {subtotal:C2}");
}
Ta metoda obliczy rabat na podstawie liczby przedmiotów w koszyku.
private decimal CalculateLevelDiscount(List<ProductModel> items, decimal subtotal)
{
if (items.Count > 3)
{
return subtotal - 3M;
}
return subtotal - items.Count;
}
Użycie Delegatów w Zdarzeniu Kliknięcia Przycisku:
messageBoxDemoButton_Click pokazuje, jak przekazywać delegaty do metody GenerateTotal i obsługiwać wyniki za pomocą okienek wiadomości.private void messageBoxDemoButton_Click(object sender, EventArgs e)
{
decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert);
MessageBox.Show($"The total is {total:C2}");
}
Uruchamianie Aplikacji:
Gdy przycisk zostanie kliknięty, aplikacja WinForms pokazuje sumę częściową i całkowitą za pomocą okien komunikatów, demonstrując elastyczność delegatów.

Tim Corey jasno wyjaśnia delegaty w C#, omawiając ich podstawy, zaawansowane użycie i praktyczne przykłady, takie jak użycie delegatów w koszyku zakupowym. Pokazuje, jak delegaty umożliwiają elastyczny i wielorazowego użytku kod, w tym Func, Action i anonimowe metody. Obejrzyj pełny film, aby nauczyć się, jak efektywnie stosować delegaty w swoich projektach!
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