《C#图解教程》读书笔记之五:委托和事件

时间:2022-05-14 06:49:58

  (1)本质:持有一个或多个方法的对象;委托和典型的对象不同,执行委托实际上是执行它所“持有”的方法。如果从C++的角度来理解委托,可以将其理解为一个类型安全的、面向对象的函数指针

《C#图解教程》读书笔记之五:委托和事件

  (2)如何使用委托?

    ①声明委托类型(delegate关键字)

    ②使用该委托类型声明一个委托变量

    ③为委托类型增加方法

    ④调用委托执行方法

《C#图解教程》读书笔记之五:委托和事件

  (3)委托的恒定性:

  组合委托、为委托+=增加方法以及为委托-=移除方法让我们看起来像是委托被修改了,其实它们并没有被修改。事实上,委托是恒定的

  在为委托增加和移除方法时实际发生的是创建了一个新的委托,其调用列表是增加和移除后的方法结果。

《C#图解教程》读书笔记之五:委托和事件

  (4)委托实例:

  ①简单带参数委托DEMO

  delegate void MyDel(int value); //声明委托类型 class Program { void PrintLow(int value) { Console.WriteLine("{0} - LowValue", value); } void PrintHigh(int value) { Console.WriteLine("{0} - HighValue", value); } static void Main(string[] args) { Program program = new Program(); MyDel myDel; //声明委托类型 //获取0~99之间的一个随机数 Random random = new Random(); int randomValue = random.Next(99); //创建一个包含具体方法的委托对象并将其赋值给myDel变量 myDel = randomValue < 50 ? new MyDel(program.PrintLow) : new MyDel(program.PrintHigh); //执行委托 myDel(randomValue); Console.ReadKey(); } }

  ②简单无参数多方法列表委托DEMO

delegate void PrintFunction(); class Test { public void Print1() { Console.WriteLine( "Print1 -- instance" ); } public static void Print2() { Console.WriteLine( "Print2 -- static" ); } } class Program { static void Main() { Test t = new Test(); PrintFunction pf; pf = t.Print1; pf += Test.Print2; pf += t.Print1; pf += Test.Print2; if ( pf != null ) { pf(); } else { Console.WriteLine( "Delegate is empty" ); } } }

  ③带返回值的委托DEMO

delegate int MyDel(); class MyClass { int IntValue = 5; public int Add2() { IntValue += 2; return IntValue; } public int Add3() { IntValue += 3; return IntValue; } } class Program { static void Main() { MyClass mc = new MyClass(); MyDel mDel = mc.Add2; mDel += mc.Add3; mDel += mc.Add2; Console.WriteLine( "Value: {0}", mDel() ); } }

二、匿名方法:不好意思,我匿了

  在委托所持有的方法中,如果某个方法只被使用一次,这种情况下,除了创建委托语法的需要,没有必要创建独立的具名方法。因此,匿名方法应运而生。

  匿名方法是在初始化委托时内联(inline)声明的方法

  下面来看看在两个版本的代码:具名方法和匿名方法的比较,匿名方法是不是简洁得多?

  ①具名参数

 View Code

   ②匿名参数

 View Code

三、Lambda表达式:好吃的语法糖

  (1)本质:简化语法的”语法糖“;

Lambda来源:1920年到1930年期间,数学家Alonzo Church等人发明了Lambda积分。Lambda积分是用于表示函数的一套系统,它使用希腊字母Lambda(λ)来表示无名函数。近年来,函数式编程语言(如Lisp)使用这个术语来表示可以直接描述函数定义的表达式,表达式不再需要有名字了。

  (2)要点:

    ①Lambda表达式中的参数列表(参数数量、类型和位置)必须与委托相匹配;

    ②表达式中的参数列表不一定需要包含类型,除非委托有ref或out关键字(此时必须显示声明);

    ③如果没有参数,必须使用一组空的圆括号;

  (3)语法:

《C#图解教程》读书笔记之五:委托和事件

四、事件初窥:发布者和订阅者模式