引用方法

在C++,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。

C# 委托 定义了返回类型和参数的类型。委托类包含对方法的引用,还可以包含多个方法引用。

定义委托

 public delegate double TwoLongsOp(long first, long second);

 public delegate string GetAString();

委托派生自 System.MulticastDelegate,而 System.MulticastDelegate 又派生自 System.Delegate。

public delegate string GetAString();

static void Main(string[] args)
{
int x = ;
Console.WriteLine(x.ToString()); GetAString stringFun = new GetAString(x.ToString);
Console.WriteLine(stringFun());
} // 以下两种方法一样
stringFun();
stringFun.Invoke();
 GetAString stringFun = new GetAString(x.ToString);
GetAString stringFun2 = x.ToString;

委托它们类型是安全的,可以确保被调用的方法的签名是正确的。但它们不关心什么类型的对象上调用该方法,甚至不考虑该方法是静态方法,还是实例方法。

class MyClass
{
public static string getStr()
{
return "Hello";
}
} static void Main(string[] args)
{
GetAString stringFun = MyClass.getStr;
Console.WriteLine(stringFun());
}

委托数组

 GetAString[] stringFun = { MyClass.getStr };
Console.WriteLine(stringFun[]());

泛型 Action<T> 委托表示引用一个 void 返回类型的方法。Action 可以调用 0 ~ 16 个参数的方法。

Func<T> 引用 带 返回类型的方法,Func可以调用 0 ~ 16 个参数的方法。

class MyClass
{
public static string getString(string s)
{
return "Hello "+ s;
} public static void Call()
{
Console.WriteLine("Hello Call");
} } static void Main(string[] args)
{
Func<string, string> stringFun = MyClass.getString;
Console.WriteLine(stringFun("Wo"));
Action fun2 = MyClass.Call;
fun2();
}

多播委托

存储两个方法的引用

增加 +=   删除 -=

class MyClass
{
public static void Hello(string s)
{
Console.WriteLine("Hello " + s);
} public static void Call(string s)
{
Console.WriteLine("Call " + s);
} } static void Main(string[] args)
{
Action<string> action = MyClass.Hello;
action += MyClass.Call; action("Zhao"); action -= MyClass.Call; action("Zhao2");
}

如果 Hello 方法报错了,第二个 Call 就不会执行了。可以用以下代替。

Action<string> action = MyClass.Hello;
action += MyClass.Call; Delegate[] delegates = action.GetInvocationList();
foreach (Action<string> action2 in delegates)
{
try
{
action2("Python");
}
catch (Exception)
{
}
}

匿名方法

Action<string> action = delegate(string str)
{
Console.WriteLine("Anonymous " + str);
}; Delegate[] delegates = action.GetInvocationList();
foreach (Action<string> action2 in delegates)
{
try
{
action2("Python");
}
catch (Exception)
{
}
}

匿名方法不能使用跳转语句(break、goto 或 continue)跳到该匿名方法的外部。匿名方法内部能访问不安全的代码。也不能使用 ref 和 out 参数。但可以使用匿名方法外部定义的其他变量。

lmadba

Action<string> action = str => Console.WriteLine("lambda " + str);
Action<string> action2 = (str) => { Console.WriteLine("lambda " + str); };

匿名方法

int sum = ;
Func<int, int> fun = x => x + sum;
Console.WriteLine(fun() + " " + sum);

事件

class Program
{
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string car)
{
this.Car = car;
} public string Car { get; private set; }
} public static event EventHandler<CustomEventArgs> NewEvent; static void Main(string[] args)
{
NewEvent += NewEventHandler;
NewEvent += NewEventHandler;
NewEvent -= NewEventHandler;
CustomEventArgs eventArgs = new CustomEventArgs("Audio");
NewEvent(null, eventArgs);
} static void NewEventHandler(object sender, CustomEventArgs e)
{
Console.WriteLine("事件处理参数 " + e.Car);
}
}
 NewEvent += NewEventHandler;        // 添加事件
NewEvent -= NewEventHandler; // 移除事件

弱事件

在不需要使用事件时,需要移除事件。否则的话,会出现内存泄露。另一种方法用弱事件。

public class WeakCarInfoEventManager : WeakEventManager
{
public static void AddListener(object source, IWeakEventListener listener)
{
CurrentManager.ProtectedAddListener(source, listener);
} public static void RemoveListener(object source, IWeakEventListener listener)
{
CurrentManager.ProtectedRemoveListener(source, listener);
} public static WeakCarInfoEventManager CurrentManager
{
get
{
WeakCarInfoEventManager manager = GetCurrentManager(typeof(WeakCarInfoEventManager)) as WeakCarInfoEventManager;
if (manager == null)
{
manager = new WeakCarInfoEventManager();
SetCurrentManager(typeof(WeakCarInfoEventManager), manager);
}
return manager;
}
} protected override void StartListening(object source)
{
(source as CarDealer).NewCarInfo += CarDealer_NewCarInfo;
} void CarDealer_NewCarInfo(object sender, CarInfoEventArgs e)
{
DeliverEvent(sender, e);
}
protected override void StopListening(object source)
{
(source as CarDealer).NewCarInfo -= CarDealer_NewCarInfo;
}
}

侦听

var dealer = new CarDealer();

var michael = new Consumer("Michael");
WeakCarInfoEventManager.AddListener(dealer, michael); dealer.NewCar("Mercedes"); var sebastian = new Consumer("Sebastian");
WeakCarInfoEventManager.AddListener(dealer, sebastian); dealer.NewCar("Ferrari"); WeakCarInfoEventManager.RemoveListener(dealer, michael); dealer.NewCar("Red Bull Racing");

还可以用内置的 泛型弱事件 写的代码更少

var dealer = new CarDealer();

var michael = new Consumer("Michael");
WeakEventManager<CarDealer, CarInfoEventArgs>.AddHandler(dealer, "NewCarInfo", michael.NewCarIsHere); dealer.NewCar("Mercedes"); var sebastian = new Consumer("Sebastian");
WeakEventManager<CarDealer, CarInfoEventArgs>.AddHandler(dealer, "NewCarInfo", sebastian.NewCarIsHere); dealer.NewCar("Ferrari"); WeakEventManager<CarDealer, CarInfoEventArgs>.RemoveHandler(dealer, "NewCarInfo", michael.NewCarIsHere); dealer.NewCar("Red Bull Racing");

C# 委托、lambda表达式和事件 (7) 持续更新的更多相关文章

  1. C#编程 委托 Lambda表达式和事件

    委托 如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字段和方 ...

  2. C#学习笔记三(委托·lambda表达式和事件,字符串和正则表达式,集合,特殊的集合)

    委托和事件的区别 序号 区别 委托 事件 1 是否可以使用=来赋值 是 否 2 是否可以在类外部进行调用 是 否 3 是否是一个类型 是 否,事件修饰的是一个对象 public delegate vo ...

  3. 委托、Lambda表达式、事件系列07,使用EventHandler委托

    谈到事件注册,EventHandler是最常用的. EventHandler是一个委托,接收2个形参.sender是指事件的发起者,e代表事件参数. □ 使用EventHandler实现猜拳游戏 使用 ...

  4. 委托、Lambda表达式、事件系列06,使用Action实现观察者模式,体验委托和事件的区别

    在"实现观察者模式(Observer Pattern)的2种方式"中,曾经通过接口的方式.委托与事件的方式实现过观察者模式.本篇体验使用Action实现此模式,并从中体验委托与事件 ...

  5. 委托、Lambda表达式、事件系列05,Action委托与闭包

    来看使用Action委托的一个实例: static void Main(string[] args) { int i = 0; Action a = () => i++; a(); a(); C ...

  6. 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理

    委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...

  7. 委托、Lambda表达式、事件系列03,从委托到Lamda表达式

    在"委托.Lambda表达式.事件系列02,什么时候该用委托"一文中,使用委托让代码简洁了不少. namespace ConsoleApplication2 { internal ...

  8. 委托、Lambda表达式、事件系列02,什么时候该用委托

    假设要找出整型集合中小于5的数. static void Main(string[] args) { IEnumerable<int> source = new List<int&g ...

  9. 委托、Lambda表达式、事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性

    委托是一个类. namespace ConsoleApplication1 { internal delegate void MyDelegate(int val); class Program { ...

  10. C#高级编程(第9版) 第08章 委托、lambda表达式和事件 笔记

          本章代码分为以下几个主要的示例文件: 1. 简单委托 2. 冒泡排序 3. lambda表达式 4. 事件示例 5. 弱事件     引用方法 委托是寻址方法的.NET版本.在C++中函数 ...

随机推荐

  1. Red And Green

    #include <stdio.h> #include <string.h> #define LENGTH 50 /* * 1.字符序列中有一个字符肯定是分界点,它的左边全为红 ...

  2. 获取淘宝客推广位id(adzone_id)

    在 获取淘宝联盟选品库的宝贝信息 这个接口中需要用到 推广位id,那边这个ID在哪找呢?1.进入阿里妈妈后台>推广管理>推广位管理,如下图: 2.在推广位管理 列表页 找到 PID,最后一 ...

  3. Shortest Unsorted Continuous Subarray

    Given an integer array, you need to find one continuous subarray that if you only sort this subarray ...

  4. kafka 名词解释及原理解析过程(三)

    为什么要了解这些名词的解释呢?因为在学一个新的知识或者领域的时候,我们需要知道它所定义的概念和名词意思,因为只有这样我们才能理解和掌握这个新的知识点,才能更加系统的掌握这个技术. 一.名词解释 1.b ...

  5. loadrunner如何监控linux,以及重点指标分析

    监控UNIX一. lr监控UNIX ,UNIX先启动一rstatd服务 以下是在IBM AIX系统中启动rstatd服务的方法: 1. 使用telnet以root用户的身份登录入AIX系统 2. 在命 ...

  6. 网络编程[第三篇]基于tcp协议实现远程连接

    需要用到subprogress模块来远程控制cmd控制台程序来得到控制台的输出信息 一.服务端 —— 控制输出信息 import socket import subprocess #socket实例化 ...

  7. Pycharm 配置houdini

    一.houdini开发环境配置 1.添加Python可执行文件 2.设置代码自动补全 刚刚添加的Python.exe,右侧点击加号,依次添加以上长方形中的文件,路径会根据个人安装路径有所变化,后面的目 ...

  8. Java多线程(九):生产者消费者模型

    生产者消费者模型 生产者:生产任务的个体: 消费者:消费任务的个体: 缓冲区:是生产者和消费者之间的媒介,对生产者和消费者解耦. 当 缓冲区元素为满,生产者无法生产,消费者继续消费: 缓冲区元素为空, ...

  9. C语言 读取配置文件

    配置文件截图: 读取结果截图: 代码转自:http://www.tuicool.com/articles/Zb2iIn 附代码: // ReadConfig.cpp : 定义控制台应用程序的入口点. ...

  10. STM32-移植FATFS的NANDFLASH驱动

    一,建立工程FATFS源码 1,在http://elm-chan.org/fsw/ff/00index_e.html上下载ff007c.zip,并把ff007c.zip里面的 src文件夹复制到D:\ ...