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
C# 中的委托是一项强大的功能,但许多开发人员并不熟悉如何有效地使用它们。 Tim Corey 的视频" C# 中的委托 - 实际演示,包括 Action 和 Func "对委托是什么、如何使用它们以及为什么它们有用进行了详尽的解释。
本文将为您提供 Tim 关于 C# 中委托的专家见解,清晰地解释其用法和实际应用。 您将学习委托如何增强代码的灵活性和效率,例如在购物车系统中使用委托的示例。
Tim 介绍了委托的概念,强调了委托在 C# 中的强大功能和多功能性。 他向观众保证,尽管有些术语令人望而生畏,但代表制的基本原理很简单。 Tim 旨在揭开委托的神秘面纱,并介绍 func 和 action 等特殊类型。
Tim 设置了一个演示应用程序来说明委托的用法。 该解决方案包含三个项目:控制台 UI、演示库和 WinForm 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 ClassImports 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 解释了演示应用程序的结构和功能:
*购物车模型:表示购物车,其中包含商品列表(ProductModel),并根据小计计算折扣后的总成本。
*产品模型:表示具有名称和价格属性的单个商品。
*控制台应用程序:用演示数据填充购物车,计算总价,并显示总价。
Tim 详细讲解了 GenerateTotal 方法中的折扣逻辑,解释了小计如何决定应用的折扣:
Tim 使用断点来演示计算和折扣逻辑,确保观众在向代表介绍之前理解基础知识。
在本节中,Tim Corey 将深入探讨 C# 中的委托概念,解释其工作原理,并通过实际代码示例演示其用法。
Tim解释说,委托本质上是一种将方法作为参数传递的方式。 与其传递变量或属性,不如传递方法,这样可以编写更灵活、更可重用的代码。
以下是 Tim 对创建和使用委托过程的详细讲解:
1.定义委托:
public delegate void MentionDiscount(decimal subtotal);public delegate void MentionDiscount(decimal subtotal);Public Delegate Sub MentionDiscount(subtotal As Decimal)Public Delegate Sub MentionDiscount(subtotal As Decimal)2.在方法中使用委托:
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;
}
}Public Function GenerateTotal(mentionDiscount As MentionDiscount) As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
' Call a method passed as a delegate
mentionDiscount(subtotal)
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 FunctionPublic Function GenerateTotal(mentionDiscount As MentionDiscount) As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
' Call a method passed as a delegate
mentionDiscount(subtotal)
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 Function3.创建要传递给委托的方法:
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}");
}Private Shared Sub SubtotalAlert(ByVal subtotal As Decimal)
Console.WriteLine($"The subtotal is {subtotal:C2}")
End SubPrivate Shared Sub SubtotalAlert(ByVal subtotal As Decimal)
Console.WriteLine($"The subtotal is {subtotal:C2}")
End Sub4.调用 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 });
}
}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
Private Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(AddressOf SubtotalAlert):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 ClassClass Program
Private Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(AddressOf SubtotalAlert):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 ClassTim 运行该应用程序来演示委托是如何工作的。 控制台输出显示了购物车的小计和总计,表明 SubtotalAlert 方法已通过委托成功传递和执行。

Tim Corey 随后探讨了 C# 中 func 和 action delegate 的使用。 这些是微软提供的特殊类型的委托,旨在简化泛型委托的使用。
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 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 FunctionPublic 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 个输入参数。
1.定义函数委托:
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);
}Public Function GenerateTotal(calculateDiscountedTotal As Func(Of List(Of ProductModel), Decimal, Decimal)) As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
MentionDiscount(subtotal)
Return calculateDiscountedTotal(Items, subtotal)
End FunctionPublic Function GenerateTotal(calculateDiscountedTotal As Func(Of List(Of ProductModel), Decimal, Decimal)) As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
MentionDiscount(subtotal)
Return calculateDiscountedTotal(Items, subtotal)
End Function2.创建折扣计算方法:
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;
}
}Private Shared Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
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 FunctionPrivate Shared Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
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 Function3.将方法传递给函数委托:
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;
}
}
}Class Program
Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(AddressOf CalculateLevelDiscount):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
Private Shared Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
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 ClassClass Program
Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(AddressOf CalculateLevelDiscount):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
Private Shared Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
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 ClassTim 演示了修改后的应用程序,表明它运行正常,并能根据提供的逻辑动态计算折扣。

Tim 对比了自定义委托和函数委托:
*委托:需要明确定义签名,提供清晰的文档和结构。
*函数:更简洁,但每次都需要指定输入和输出类型,这可能不太清晰。
两种方法都提供了灵活性,但选择取决于具体的使用案例和应用程序的复杂程度。
Tim Corey 回答了一个关于使用委托的常见问题:如果所有工作似乎都在其他地方完成,为什么还要使用委托呢?
Tim解释说,委托的目的是为代码提供灵活性和可扩展性。 ShoppingCartModel 类中的 GenerateTotal 方法可能不仅仅用于计算折扣。 它还可以处理诸如检查库存可用性、验证购物车内容或其他业务逻辑等任务。 委托允许您传递特定方法以执行特殊任务或自定义行为,而无需更改核心方法。 这使得代码更具模块化,更易于维护。
在以下情况下,委托尤其有用:
Tim 介绍了 Action 委托,这是 C# 中的另一种特殊类型的委托。 Action 委托类似于 Func,但它不返回值(即,它返回 void)。
1.创建操作委托:
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);
}Public Function GenerateTotal(calculateDiscountedTotal As Func(Of List(Of ProductModel), Decimal, Decimal), tellUserWeAreDiscounting As Action(Of String)) As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
MentionSubtotal(subtotal)
tellUserWeAreDiscounting("We are applying your discount.")
Return calculateDiscountedTotal(Items, subtotal)
End FunctionPublic Function GenerateTotal(calculateDiscountedTotal As Func(Of List(Of ProductModel), Decimal, Decimal), tellUserWeAreDiscounting As Action(Of String)) As Decimal
Dim subtotal As Decimal = Items.Sum(Function(x) x.Price)
MentionSubtotal(subtotal)
tellUserWeAreDiscounting("We are applying your discount.")
Return calculateDiscountedTotal(Items, subtotal)
End Function2.创建警报方法:
private static void AlertUser(string message)
{
Console.WriteLine(message);
}private static void AlertUser(string message)
{
Console.WriteLine(message);
}Private Shared Sub AlertUser(message As String)
Console.WriteLine(message)
End SubPrivate Shared Sub AlertUser(message As String)
Console.WriteLine(message)
End Sub3.将方法传递给操作委托:
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);
}
}Class Program
Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(AddressOf CalculateLevelDiscount, AddressOf AlertUser):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
Private Shared Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
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
Private Shared Sub AlertUser(message As String)
Console.WriteLine(message)
End Sub
End ClassClass Program
Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(AddressOf CalculateLevelDiscount, AddressOf AlertUser):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
Private Shared Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
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
Private Shared Sub AlertUser(message As String)
Console.WriteLine(message)
End Sub
End ClassTim 展示了如何使用匿名方法,允许你动态定义方法而无需命名它们。
1.定义匿名方法:
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 });
}
}Class Program
Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(Function(items, subtotal)
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,
Sub(message) Console.WriteLine(message)):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 ClassClass Program
Shared cart As New ShoppingCartModel()
Shared Sub Main(args As String())
PopulateCartWithDemoData()
Console.WriteLine($"The total for the cart is {cart.GenerateTotal(Function(items, subtotal)
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,
Sub(message) Console.WriteLine(message)):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 Class2.理解语法:
=> 运算符(lambda表达式)直接在行内定义方法体。通过使用委托(包括 Func、Action 和匿名方法),开发人员可以创建更动态、模块化的代码,从而实现灵活且可重用的组件。
在本部分中,Tim Corey 通过将委托的使用扩展到 WinForms 应用程序来演示委托的强大功能。 这突显了委托如何在各种用户界面 (UI) 环境中促进不同的行为。
1.带有两个按钮的 WinForm 用户界面:
该表单有两个按钮:一个用于演示消息框,一个用于演示文本框。
此外,还包括 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 : 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 ClassPublic 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 PrintOutDiscountAlert(string message)
{
MessageBox.Show(message);
}Private Sub PrintOutDiscountAlert(ByVal message As String)
MessageBox.Show(message)
End SubPrivate Sub PrintOutDiscountAlert(ByVal message As String)
MessageBox.Show(message)
End Sub2.小计提醒:
private void SubtotalAlert(decimal subtotal)
{
MessageBox.Show($"The subtotal is {subtotal:C2}");
}private void SubtotalAlert(decimal subtotal)
{
MessageBox.Show($"The subtotal is {subtotal:C2}");
}Private Sub SubtotalAlert(ByVal subtotal As Decimal)
MessageBox.Show($"The subtotal is {subtotal:C2}")
End SubPrivate Sub SubtotalAlert(ByVal subtotal As Decimal)
MessageBox.Show($"The subtotal is {subtotal:C2}")
End Sub3.计算等级折扣:
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;
}Private Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
If items.Count > 3 Then
Return subtotal - 3D
End If
Return subtotal - items.Count
End FunctionPrivate Function CalculateLevelDiscount(items As List(Of ProductModel), subtotal As Decimal) As Decimal
If items.Count > 3 Then
Return subtotal - 3D
End If
Return subtotal - items.Count
End Function1.在按钮点击事件中使用委托:
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}");
}private void messageBoxDemoButton_Click(object sender, EventArgs e)
{
decimal total = cart.GenerateTotal(SubtotalAlert, CalculateLevelDiscount, PrintOutDiscountAlert);
MessageBox.Show($"The total is {total:C2}");
}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 SubPrivate 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 Sub2.运行应用程序:

Tim Corey 对 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