网站建设wuliankj,信息查询系统,西安公司注册代理,中国建设银行网站首页签约什么是委托委托是一种引用类型#xff0c;表示对具有特定参数列表和返回类型的方法的引用。 在实例化委托时#xff0c;你可以将其实例与任何具有兼容参数和返回类型的方法进行绑定。 你可以通过委托实例调用方法。简单的理解#xff0c;委托是方法的抽象类#xff0c;它定…什么是委托委托是一种引用类型表示对具有特定参数列表和返回类型的方法的引用。 在实例化委托时你可以将其实例与任何具有兼容参数和返回类型的方法进行绑定。 你可以通过委托实例调用方法。简单的理解委托是方法的抽象类它定义了方法的类型可以实例化。和普通的类一样可以申明变量进行赋值可以当作参数传递可以定义成属性。委托具有以下属性委托类似于 C 函数指针但委托完全面向对象不像 C 指针会记住函数委托会同时封装对象实例和方法。委托允许将方法作为参数进行传递。委托可用于定义回调方法。委托可以链接在一起具备单播、多播功能。方法不必与委托类型完全匹配。 有关详细信息请参阅使用委托中的变体。使用 Lambda 表达式可以更简练地编写内联代码块。 Lambda 表达式在某些上下文中可编译为委托类型。1.委托基础介绍1.1 delegate委托的声明使用 delegate 关键字,定义具体的委托类型Delegate至少0个参数至多32个参数可以无返回值也可以指定返回值类型。查看代码方法绑定进行调用查看代码1.2 Action 和 Func 背景抽象的 Delegate 类提供用于松散耦合和调用的基础结构但是这样看来引发一个问题无论何时需要不同的方法参数这都会创建新的委托类型。 一段时间后此操作可能变得繁琐。 每个新功能都需要新的委托类型幸运的是没有必要这样做框架已经帮我们定义Action 和 Func 类我们可以直接申明进行使用1.3 ActionT 类Action是无返回值的泛型委托。Action 委托的变体可包含多达 16 个参数如 ActionT1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16。 重要的是这些定义对每个委托参数使用不同的泛型参数这样可以具有最大的灵活性。框架源码如图使用就很方便了我们只需要直接申明委托类型进行使用例查看代码1.4 FuncT 类Func 委托的变体可包含多达 16 个输入参数如 FuncT1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult。 按照约定返回结果的类型始终是所有 Func 声明中最后一个参数的类型利用out类型参数实现。Func是有返回值的泛型委托func至少0个参数至多16个参数根据返回值泛型返回。必须有返回值不可void。框架源码如下使用就很方便了我们只需要直接申明委托类型进行使用例查看代码2. 委托实战案例我这里就做一个多播案例帮助大家理解其实.NET core 日志框架和其他第三方日志框架差不多就是这种套路2.1 定义Logger类这个类我们的定义好委托和调用委托的方法。查看代码2.2 定义文件记录器一个写入文件的文件记录器查看代码2.3 定义数据库记录器一个写入不同数据库的数据库记录器查看代码以上两个代码逻辑博主就不介绍了就用一个控制台输出代表业务代码了2.4 测试测试一下广播和委托删除效果查看代码运行效果在实际项目中大家就自行发挥3. 委托变量捕获3.1效果演示说到委托博主也把这个重要的知识点讲解一下这个知识点很多人可能不知道或者踩过坑但掌握了这个知识点其实可以实现一些比较花哨功能。这里博主就用一个案例进行体现变量捕获这里代码博主就用 lambda 表达式 进行简写不太熟悉的可以通过链接跳转进行学习。逻辑就是简单的累计一下数量通过最终的值体现。这里博主分别申明两个整数型变量通过两个委托分别累计然后看各自的值。两个委托区别就是传值方式的不同。查看代码测试效果大家发现没逻辑代码一下只是参数传递方式不一样结果截然不同委托1的方式不改变变量的值方法之间是不共享这个参数的。这种很容易理解就和我们调用普通方法一样变量是值类型是拷贝了一个副本传给了方法进行使用委托2的方式改变变量的值方法之间是共享这个参数的。这种就像引用类型参数一样是不是很神奇难道是利用了ref关键字实现的3.2原理刨析其实没有大家想学的那么神秘委托之所以使用方式和类无异是因为它本身就是一个类只是这个过程的定义由编译器帮我们做了我们只需要使用C#的语法糖。接下来博主就带大家揭开委托的神秘面纱。我也给大家画一个简单的编译》执行的过程3.2.1 委托真实面貌博主就简单写了一个委托然后通过IL DASM工具查看IL代码查看代码3.2.2模拟委托调用过程查看代码 大家发现没最终的IL代码一模一样。也就说委托就是编译器帮我们把func编译成一个带invoke函数的func类和生成一个装捕获的变量和函数体的类然后通过构造函数将对象引用和函数指针(获取指针就是大家所说的把非托管指针压入当前栈)传给func类的实例化。然后最终调用的时候委托类的invoke函数会去调用真正的函数。就这样完成了对函数的抽象。3.2.3 委托变量生命周期现在大家是不是对委托有了一定的理解了而委托涉及到的捕获变量和参数变量生命周期就说得通了也知道为啥委托改变了变量能通知到原本的变量因为对变量就行了类的装箱打包成了一个一个引用类型那方法外部当然知道变量的值被改变了因为大家都是拿着引用对象的地址呀。下面做个生命周期小总结p变量是普通变量当方法被销毁时它就会被销毁。count2变量是捕获变量当委托实例被销毁时它才会被销毁。4. 事件其实讲完委托事件就很容易理解了 博主就简单讲解一下如果大家有需要博主就再写一篇详细的讲解。事件实际上事件是建立在对委托的语言支持之上的一种设计而已。4.1 事件定义语法/定义一个委托
4publicdelegatevoiddelegateRun();
5//定义一个事件6publicevent delegateRun eventRun;简单的说事件可以看作是一个委托类型的变量4.2委托和事件共性它们都提供了一个后期绑定方案在该方案中组件通过调用仅在运行时识别的方法进行通信。 它们都支持单个和多个订阅服务器方法。 也就是单播和多播支持。 二者均支持用于添加和删除处理程序的类似语法。 最后引发事件和调用委托使用完全相同的方法调用语法。 它们甚至都支持与 ?. 运算符一起使用的相同的 Invoke() 方法语法。4.3 事件原理刨析publicevent EventHandlerNewMailEventArgs NewMail; 可以看到当我们定义一个NewEvent时编译器帮我们生成了1. 一个private NewMail 字段类型为 EventHandlerNewMailEventArgs。 2.一个 add_NewMail 方法用于将委托添加到委托链内部调用了Delegate.Combine方法。3.一个 remove_NewMail 方法用于将委托从委托链移除内部调用了Delegate.Remove方法。对事件的操作就是是对NewMail字段的操作。4.4 如何选择主要区别就是 1.事件处理程序通过修改事件参数对象的属性将信息传回到事件源。 虽然这些惯用语可发挥作用但它们不像从方法返回值那样自然。 2.包含事件的类以外的类只能添加和删除事件侦听器只有包含事件的类才能调用事件。 事件通常是公共类成员。 相比之下委托通常作为参数传递并存储为私有类成员如果它们全部存储 3.当事件源将在很长一段时间内引发事件时基于事件的设计会更加自然。比如基于事件的 UI 控件设计案例总结1事件事件时属于类的成员所以要放在类的内部。2委托属于一个定义是和类、接口类似的通常放在外部。所以事件这种架构设计思想还是很值得大家去学习的。所以说如果你的代码在不调用任何订阅服务器的情况下可完成其所有工作使用基于事件的设计会更好点。大家在项目中怎么进行选择就看实际需求了。