《Effective C#》读书笔记——条目24:用委托实现回调<使用C#表达设计>

简介:

  在C#语言中,回调是通过委托来实现的。委托为我们提供了安全的回调定义,大多数委托都和事件相关,但这不是委托的全部应用场景,当类之间需要通信,并且我们希望一种比接口更加松耦合的机制时,委托便是最佳选择。委托允许我们在运行时配置目标并且通知多个客户对象,委托对象中包含一个引用,该方法可以使静态方法也可以是实例方法。使用委托,我们可以和一个或者多个在运行时联系起来的客户对象进行通信。

 

Lambda表达式

  回调和委托在C#中非常常用,C#为委托提供了精简的语法——Lambda表达式。同时.NET还内建了很多常用的委托形式,它们包含在这三个泛型委托中:

  • Predicate<T>:表示一个提供bool返回值的函数,用来测试某个条件。
  • Action<T>:接收一系列参数,但不返回任何值
  • Func<T>接收一系列参数,返回单一结果。

 Linq中大量使用了这些概念,List<T>中也包含了很多的回调方法,如下:

复制代码
 1         static void Main(string[] args)
 2         {
 3             List<int> numbers = Enumerable.Range(1, 200).ToList();
 4             var oddNumbers = numbers.Find(n => n % 2 == 1);//返回集合中匹配的第一个元素
 5             var test = numbers.TrueForAll(n => n < 50);//是否集合中每个元素符合定义的条件,返回false
 6             numbers.RemoveAll(n => n % 2 == 0);//删除所有偶数
 7             numbers.ForEach(item => Console.WriteLine(item));//打印集合中所有元素
 8 
 9             Console.Read();
10         }
复制代码

   LINQ所有的功能都依赖于委托。回调也是用在WPF和Windows Forms中跨线程调用的封装(marshalling)上。在.NET Framework中需要传入方法的地方,框架都会使用委托,并允许调用者使用Lambda表达式提供。

 

多播委托

   C#中的委托都是多播委托(multicast delegate)。多播委托将会把所有添加到委托中的目标函数组合成一个单一的调用。在这里我们需要注意两点

1.如果有委托调用出现异常,那么委托链会被中断,这种方式不能保证安全。

2.多播委托返回的将是委托链上最后一个函数调用的返回值。

 为了解决上的问题我们可以手动遍历委托链中的每个委托目标(可以参考:使用委托和事件实现观察者模式(Observer Pattern)),通过调用委托实例的GetInvocationList(),遍历委托链中的每个目标。看下面的示例:只有每一个委托调用都返回true时,遍历才能继续。或者我们可以再遍历委托链时添加try/catch语句块,处理异常。

复制代码
 1         public void LengthyOperation(Func<bool> Pred)
 2         {
 3             bool bContinue = true;
 4             foreach (ComplicatedClass cl in container)
 5             {
 6                 c1.DoLengthyOperation();
 7                 foreach (Func<bool> pr in Pred.GetInvocationList())
 8                 {
 9                     bContinue &= pr();//等效于 bContinue = bContinue & pr();
10 
11                     if (!bContinue)
12                         return;
13                 }
14             }
15         }
复制代码

 

小节

委托是在运行时进行回调的最好方式,这种方式对客户类的要求更加简单,你可以在运行时配置委托目标。另外,委托也支持多个客户目标。在.NET中,客户回调应该使用委托来实现。

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2013/01/17/EffectiveCSharp_24.html ,如需转载请自行联系原作者
相关文章
|
3月前
|
存储 C# C++
C#进阶-委托(Delegrate)
类似于 C 或 C++ 中函数的指针,委托是C#的函数指针,是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。本篇文章我们将讲解C#里委托的类型及如何使用。委托的语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。
26 0
|
4月前
|
Java C# C++
【从Java转C#】第八章:委托、lambda、事件
【从Java转C#】第八章:委托、lambda、事件
|
4月前
|
C#
C#中的委托
C#中的委托
20 0
|
5月前
|
存储 开发框架 .NET
c#委托详解
委托是一种能够将方法作为参数传递、存储方法并且调用方法的类型,它可以让我们写出更加灵活和可扩展的代码。委托通常用于回调 (Callback) 机制,比如在事件处理、异步编程、LINQ 查询等场景中常常会使用委托。它可以将方法作为参数传递给其他方法,从而在需要的时候执行该方法。
27 2
|
8月前
|
C#
《More Effective C# 》读书笔记 第一章
《More Effective C# 》读书笔记 第一章
C#编程:如何理解委托-2
C#编程:如何理解委托-2
|
编译器 C# C++
我竟然用它搞懂了王者荣耀的技能释放机制!【C#委托】
我竟然用它搞懂了王者荣耀的技能释放机制!【C#委托】
211 0
C#委托/Func()中 GetlnvocationList()方法的使用 | 接受委托多个返回值
C#委托/Func()中 GetlnvocationList()方法的使用 | 接受委托多个返回值
252 0
C#委托/Func()中 GetlnvocationList()方法的使用 | 接受委托多个返回值
|
设计模式 前端开发 C#
C#开发中使用委托的作用和好处
先看概念,什么是委托? 从程序的角度来讲:你就可以把委托看成是用来执行方法(函数)的一个“指针” 通俗的说就是:通过委托,我们可以把方法当成参数传递。 这里我举个例子:“设想,如果我们写了一个厨师做菜的方法,里面有拿菜、切菜、配菜、炒菜四个步骤,但编写此方法代码的人想让配菜这个环节让调用方法的人来实现,换句话说,就是想把方法作为参数来传递,那么怎么来实现呢? 方法1:使用接口,这里不是我们讨论的。
7249 0
|
C#
C# 从1到Core--委托与事件(三)
委托与事件在C#1.0的时候就有了,随着C#版本的不断更新,有些写法和功能也在不断改变。本文温故一下这些改变,以及在NET Core中关于事件的一点改变。
143 0