C#基础精华07(委托事件,委托的使用,匿名方法)

摘要:
委托可以被视为指向函数的指针。匿名方法是无名方法。3+5是两个匿名int对象的添加。如果允许匿名对象,则允许匿名方法。ProcessWordDelegatep=委托{Console.WriteLine;};知道C#中有匿名方法,您可以知道这种编写方法是匿名函数。

1.委托概述

委托是一种数据类型,像类一样(可以声明委托类型变量)。方法参数可以是int、string、类类型

void M1(int n){  } √

void M2(string s){  } √

void M3(Person p){  } √

委托就是一种数据类型,用来存放方法的数据类型。

那么委托到底把方法存到哪里了?其实委托还是一个类。把方法包装成了一个委托。

方法是不能直接赋值的,那么能不能声明一个能存放方法的变量呢(委托)。像存储变量一样把方法存储起来。

2.委托的使用

声明委托的方式:delegate 返回值类型 委托类型名(参数) 比如delegate void StringProcess(string s); 注意这里的除了前面的delegate,剩下部分和声明一个函数一样,但是StringProcess不是函数名,而是委托类型名 

存储什么样的方法就声明什么类型(方法参数与返回值)的委托。

声明的委托是一种类型,就像int、Person一样,如果要用的话还要声明委托类型的变量,声明委托类型变量的方式:StringProcess f1;

将委托类型变量指向函数 StringProcess sp = new StringProcess(SayHello),这样就可以像调用普通函数一样把sp当成函数用了。委托可以看做是函数的指针。整数可以用整数变量指向它,对象可以用对象变量指向它,函数也可以用委托变量指向它。和直接调用函数的区别:用委托就可以指向任意的函数,哪怕是之前没定义的都可以,而不使用受限于那几种。

将委托类型变量指向函数还可以简化成StringProcess sp = SayHello,编译器帮我们进行了new。但是不能sp=PrintIt(),因为这样就成了函数调用。

3.委托用例

C#基础精华07(委托事件,委托的使用,匿名方法)第1张C#基础精华07(委托事件,委托的使用,匿名方法)第2张
 1 class Program
 2     {
 3         //定义一个委托类型DelegateString
 4         public delegate string DelegateString(string text);
 5         //定义一个ChangeString类
 6         public class ChangeString
 7         {
 8             //定义一个ChangeStringText方法,包含一个字符串数组和一个委托变量
 9             //ChangeText用来接收传进来的方法
10             public void ChangeStringText(string[] names,DelegateString ChangeText)
11             {
12                 for (int i = 0; i < names.Length; i++)
13                 {
14                     //调用传进来的方法改变字符串
15                     names[i] = ChangeText(names[i]);
16                 }
17             }
18         }
19         static void Main(string[] args)
20         {
21             ChangeString cs=new ChangeString();
22             string[] names = {"卡卡西","佐助","鸣人"};
23             //调用ChangeStringText方法,把names数组和JoinString方法传进去
24             cs.ChangeStringText(names, JoinString);
25             //遍历输出改变后的数组
26             for (int i = 0; i < names.Length; i++)
27             {
28                 Console.WriteLine(names[i]);
29             }
30             Console.ReadKey();
31         }
32         //定义一个NewString方法
33         public static string NewString(string name)
34         {
35             return "----"+name+"----";
36         }
37         //定义一个JoinString
38         public static string JoinString(string name)
39         {
40             return "" + name + "";
41         }
42     }
View Code

4.运行结果

传入NewString方法

C#基础精华07(委托事件,委托的使用,匿名方法)第3张
传入JoinString方法

C#基础精华07(委托事件,委托的使用,匿名方法)第4张



匿名方法

使用Delegate的时候很多时候没必要使用一个普通的方法,因为这个方法只有这个Delegate会用,并且只用一次,这时候使用匿名方法最合适。
匿名方法就是没有名字的方法。3就是没有名字的int对象。3+5就是两个匿名int对象的相加,允许匿名对象,就允许匿名方法。

 ProcessWordDelegate p = delegate(string s)
            {
                Console.WriteLine(s);
            };

知道C#中有匿名方法,看到这种写法知道是匿名函数即可。
匿名方法与lambda表达式最终编译为一个方法。

MyDelete md = delegate() { Console.WriteLine("嘎嘎"); };
md();

================================================================
 public delegate void SayDelegate();
    SayDelegate say = () => { Console.WriteLine("hhh"); };
public delegate int MyDelete2(int num);
MyDelete2 md2 = delegate(int number) { return number + 10; };
            int result= md2(20);
            Console.WriteLine(result);
            Console.ReadKey();

================================================================
 public  delegate  string SayDelegate(string n);
    SayDelegate say = x => x+"好帅";
            Console.WriteLine(say("小杨"));

===============================================================
 T1((x, y, z) => x - y + z);
        public static void T1(SayDelegate say)
        {
            int result = say(10, 20, 30);
            Console.WriteLine(result);
        }
 public delegate int SayDelegate(int n1, int n2, int n3);

===============================================================
 List<int> list = new List<int>() { 1,2,3,4,5,6,7,8,9};
            IEnumerable ieor= list.Where(x=>x>5);
            foreach (int item in ieor)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();

==============================================================



多播委托*(委托链,委托的组合)

delegate void ProcessWordDelegate(string s)
ProcessWordDelegate d = new ProcessWordDelegate(SayHello)+new ProcessWordDelegate(ToLower)
多播委托如何处理返回值?
委托绑定多个方法后,其中一个方法执行发生异常后面的方法还会继续执行吗?不会!
一个重要的方法GetInvocationList();//返回一个Delegate[]类型。Delegate类是一个抽象类,是所有委托的父类。
组合的委托必须是同一个类型
相当于创建了一个按照组合的顺序依次调用的新委托对象。
委托的组合一般是给事件用的,用普通的委托的时候很少用

为委托的增减方法

d+=SayHello,为委托增加一个方法,不要感觉奇怪,因为它就是d=d+ SayHello
d-=SayHello,将方法从委托中移除。
Delegate.Combine();


委托的一些应用:
凡是需要回调的地方都能用到委托。
自定义类(控件、通信类……(事件))
多线程
窗体之间回传值
正则表达式中替换Email掩码Replace()

委托的本质1(*)

其实就是一个类把方法包装了一下,委托都继承自System.MulticastDelegate,而System.MulticastDelegate又继承自System.Delegate
多播委托就是有一个委托数组,依次调用。

 class Program
    {
        static void Main(string[] args)
        {
            UpdateDelegate upde = M1;
            upde += M2;
            upde += M3;
            upde -= M2;
            upde = M4;
            upde();

            Console.ReadKey();     //输出 M1 M2 M3 M4 
        }
        public static void M1()
        {
            Console.WriteLine("M1");
        }
        public static void M2()
        {
            Console.WriteLine("M2");
        }
        public static void M3()
        {
            Console.WriteLine("M3");
        }
        public static void M4()
        {
            Console.WriteLine("M4");
        }
    }
    public delegate void UpdateDelegate();

===================================================================
ResultDelegate M1 = T1;
            M1 += T2;
            M1 += T3;
            M1 += T4;
            int r = M1();
            Console.WriteLine(r);
            Console.ReadKey();
    //输出M4
 public static int T1()
        {
            return 1;
        }
        public static int T2()
        {
            return 2;
        }
        public static int T3()
        {
            return 3;
        }
        public static int T4()
        {
            return 4;
        }
public delegate int ResultDelegate();
===========================================================
 Delegate[]des=  M1.GetInvocationList();
          foreach (Delegate item in des)
          {
              ResultDelegate res = item as ResultDelegate;
              Console.WriteLine(res());
          }

=============================================================单独拿到里面每个方法




事件(通过委托实现的,委托才是事件能正常执行的核心内容)

事件语法:event ProcessWordDelegate 例子 OnInt
加了event关键字实现事件机制的好处:用了event事件,不可以修改事件已经注册的值;不可以冒充进行事件通知了。在IntUC类外部就不能通过OnInt(3)的方式调用注册的委托了。只能+=、-=!


事件本质论

event会自动生成一个private delegate变量和两个函数: add和remove,C#编译器用这两个方法支持+=和-=操作符 (*)。C#<>.Net。
public event MyDelegate OnEvent;
内部实现是(示例性)
private MyDelegate OnEvent;
public void Add(MyDelegate d)
{
   OnEvent+=d;
}
public void Remove(MyDelegate d)
{
   OnEvent-=d;
}
因为OnEvent是private的,所以在类外部不能OnEvent(1)触发事件,但是在类内部可以。
public的方法只有Add和Remove,所以只能+=、-=,其他的操作都是不可以的。

C#基础精华07(委托事件,委托的使用,匿名方法)第5张


委托和事件的区别(常考)

委托和事件没有可比性,因为委托是数据类型,事件是对象(可以理解为对委托变量的封装。),下面说的是委托的对象(用委托方式实现的事件)和(标准的event方式实现)事件的区别。事件的内部是用委托实现的。(举例子:三种实现事件方式的区别(直接用委托实现、用私有委托+公有方法模拟事件,直接用event事件实现))
因为对于事件来讲,外部只能“注册自己+=、注销自己-=”,外界不可以注销其他的注册者,外界不可以主动触发事件,因此如果用Delegate就没法进行上面的控制,因此诞生了事件这种语法。add、remove。
事件是用来阉割委托实例的。事件只能add、remove自己,不能赋值。事件只能+=、-=,不能=、不能外部触发事件。

免责声明:文章转载自《C#基础精华07(委托事件,委托的使用,匿名方法)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vs2017 编译最新chromium容器编排系统K8s之包管理器Helm基础使用(二)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

权限认证机制

一、Form表单认证 之前的项目以MVC为主,采用的是from表单认证,Forms认证示意图如下: HTTP是一个无状态的协议,WEB服务器在处理所有传入HTTP请求时,根本就不知道某个请求是否是一个用户的第一次请求与后续请求,或者是另一个用户的请求。 WEB服务器每次在处理请求时,都会按照用户所访问的资源所对应的处理代码,从头到尾执行一遍,然后输出响应...

php Redis函数使用总结(string,hash,list, set , sort set )

  对于:string, set , sort set , hash 的增,改操作,是同一个命令,但是把它当改操作时,及时成功返回值依旧为0 对于:list结构来说,增删改查自有一套方法。   1 <?php 2 /*1.Connection*/ 3 $redis = new Redis(); 4 $redis-...

java操作Redis

Java访问redis Java操作redis string(字符串) hash(哈希) list(列表) set(集合)  zset(sorted set:有序集合) package com.cjh; import redis.clients.jedis.Jedis; /** * @author * @site * @company * @...

JSSDK实现微信自定义分享---java 后端获取签名信息

一、首先说下关于微信Access_token的问题,微信Access_token分为2中: 1.授权token获取方式: 这种token需要code值(如何获取code值查看官方文档) 1 "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret="...

Unity3D研究之支持中文与本地文件的读取写入(转)

前几天有个朋友问我为什么在IOS平台中可以正常的读写文件可是在Android平台中就无法正常的读写。当时因为在上班所以我没时间来帮他解决,晚上回家后我就拿起安卓手机真机调试很快就定位问题所在,原来是他文件的路径写错了。开发中往往一道很难的问题解开的时候发现原来真的非常的简单,哇咔咔。 刚好在MOMO的书中也有涉及到文件的读取与写入,那么本节我将书中的部分...

C++篇实现MD5算法

1、头文件 #ifndef MD5_H  #define MD5_H  #include <string>  #include <fstream>  /* Type define */  typedef unsigned char byte;  typedef unsigned int uint32;  using std::st...