隐藏

C#什么是委托、如何定义委托及委托实例化、委托如何使用

发布:2023/12/7 15:48:53作者:大数据 来源:大数据 浏览次数:448

委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。 在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。 你可以通过委托实例调用方法。

委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 你可以创建一个自定义方法,当发生特定事件时,某个类(如 Windows 控件)就可以调用你的方法。 下面的示例演示了一个委托声明:

C#

 

可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。 该方法可以是静态方法,也可以是实例方法。 此灵活性意味着你可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。

 备注

在方法重载的上下文中,方法的签名不包括返回值。 但在委托的上下文中,签名包括返回值。 换句话说,方法和委托必须具有相同的返回类型。

将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。 可编写一个比较应用程序中两个对象的方法。 该方法可用在排序算法的委托中。 由于比较代码与库分离,因此排序方法可能更常见。

对于类似的方案,已将函数指针添加到 C# 9,其中你需要对调用约定有更多的控制。 使用添加到委托类型的虚方法调用与委托关联的代码。 使用函数指针,可以指定不同的约定。

委托概述

委托具有以下属性:

  • 委托类似于 C++ 函数指针,但委托完全面向对象,不像 C++ 指针会记住函数,委托会同时封装对象实例和方法。
  • 委托允许将方法作为参数进行传递。
  • 委托可用于定义回调方法。
  • 委托可以链接在一起;例如,可以对一个事件调用多个方法。
  • 方法不必与委托类型完全匹配。 有关详细信息,请参阅使用委托中的变体。
  • 使用 Lambda 表达式可以更简练地编写内联代码块。 Lambda 表达式(在某些上下文中)可编译为委托类型。 若要详细了解 lambda 表达式,请参阅 lambda 表达式。

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/delegates/how-to-declare-instantiate-and-use-a-delegate

在 C# 1.0 和更高版本中,可以如下面的示例所示声明委托。

C#

 

C#

 

C# 2.0 提供了更简单的方法来编写前面的声明,如下面的示例所示。

C#

 

在 C# 2.0 和更高版本中,还可以使用匿名方法来声明和初始化委托,如下面的示例所示。

C#

 

在 C# 3.0 和更高版本中,还可以通过使用 lambda 表达式声明和实例化委托,如下面的示例所示。

C#

有关详细信息,请参阅 Lambda 表达式。

下面的示例演示如何声明、实例化和使用委托。 BookDB 类封装用来维护书籍数据库的书店数据库。 它公开一个方法 ProcessPaperbackBooks,用于在数据库中查找所有平装书并为每本书调用委托。 使用的 delegate 类型名为 ProcessBookCallback。 Test 类使用此类打印平装书的书名和平均价格。

使用委托提升书店数据库和客户端代码之间的良好分隔功能。 客户端代码程序不知道如何存储书籍或书店代码如何查找平装书。 书店代码不知道它在找到平装书之后对其执行什么处理。

示例

C#

 

可靠编程

  • 声明委托。以下语句声明新的委托类型。

    C#

     

    每个委托类型描述自变量的数量和类型,以及它可以封装的方法的返回值类型。 每当需要一组新的自变量类型或返回值类型,则必须声明一个新的委托类型。

  • 实例化委托。声明委托类型后,则必须创建委托对象并将其与特定的方法相关联。 在上例中,你通过将 PrintTitle 方法传递给 ProcessPaperbackBooks 方法执行此操作,如下面的示例所示:

    C#

    这将创建一个新的与静态方法 关联的委托对象。 同样,如下面的示例所示,传递对象 totaller 中的非静态方法 AddBookToTotal

    C#

    在这两种情况下,都将新的委托对象传递给 ProcessPaperbackBooks 方法。

    创建委托后,它与之关联的方法就永远不会更改;委托对象是不可变的。

  • 调用委托。创建委托对象后,通常会将委托对象传递给将调用该委托的其他代码。 委托对象是通过使用委托对象的名称调用的,后跟用圆括号括起来的将传递给委托的自变量。 下面是一个委托调用示例:

    C#

    委托可以同步调用(如在本例中)或通过使用 BeginInvoke 和 EndInvoke 方法异步调用。

声明:本站内容来源于原创和互联网,尊重作者版权,转载请注明来源网址,欢迎收藏,谢谢!