第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托?

一,什么是委托?

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

(一个委托是一个指向一个方法的引用,或者说,一个委托的实例就是一个指向某个方法的对象)。

二,为什么要学习委托?

1,通常情况下:当项目中所需的功能(需求)越多,则相应需要的方法也就越多,一般做法是每个功能(需求)单独学方法,但是这样会造成代码冗余。

例如:三个需求
            //1、将一个字符串数组中每个元素都转换成大写
            //2、将一个字符串数组中每个元素都转换成小写
            //3、将一个字符串数组中每个元素两边都加上 双引号

class Program
{
static void Main(string[] args)
{
//三个需求
//1、将一个字符串数组中每个元素都转换成大写
//2、将一个字符串数组中每个元素都转换成小写
//3、将一个字符串数组中每个元素两边都加上 双引号
string[] words = { "abCDefG", "HIJKlmnOP", "QRsTuvW", "XyZ" };
////////////////普通方法调用函数////////
ProStToUpper(words);
ProStrToLower(words);
ProStrSYH(words); }
//三个具体的方法 的定义
public static void ProStToUpper(string[] word)
{
for (int i = ; i < word.Length; i++)
{
word[i] = word[i].ToUpper();
}
}
public static void ProStrToLower(string[] word)
{
for (int i = ; i < word.Length; i++)
{
word[i] = word[i].ToLower();
}
}
public static void ProStrSYH(string[] word)
{
for (int i = ; i < word.Length; i++)
{
word[i] = "\"" + word[i] + "\"";
}
} }

2,有没有一种好的方法可以将代码中的一些方法提出来并将方法作为参数当需要时作为参数传递实现功能,即将方法作为参数????  因此需要某种类型的形参来接受作为参数的方法的传递,即有一个参数可以接受传递的方法参数。???  这种类型为委托类型,传递的方法为委托方法

public delegate string DelProStr(string words);  //////////////////////////////////////////////(1)声明委托 (在类的外部声明 返回值类型+参数类型及个数)
class Program
{
static void Main(string[] args)
{
//三个需求
//1、将一个字符串数组中每个元素都转换成大写
//2、将一个字符串数组中每个元素都转换成小写
//3、将一个字符串数组中每个元素两边都加上 双引号
string[] words = { "abCDefG", "HIJKlmnOP", "QRsTuvW", "XyZ" }; //1. ProStr(words, StrToUpper); //2. ProStr(words, StrToLower);
//
ProStr(words, StrSYH);//传参 方法(StrSYH)作为参数 (3)将委托与具体方法绑定
for (int i = ; i < words.Length; i++)
{
Console.WriteLine(words[i]);
}
Console.ReadKey();
} public static void ProStr(string[] word, DelProStr del)
//传参时 DelProStr del=StrToUpper或(StrToLower)或(StrSYH):《=》 DelProStr del= new DelProStr(具体方法);委托所指向的函数必须跟委托具有相同的签名:相同的返回值类型+参数类型及个数
{
for (int i = ; i < word.Length; i++)
{
word[i] = del(word[i]); ///////////////(4)委托调用
}
}
/////////////////////////////////////////////////////////////////////////////////////////(2)根据委托定义具体方法/////////
public static string StrToUpper(string word)//具体方法1
{
return word.ToUpper();
}
public static string StrToLower(string word)//具体方法2
{
return word.ToLower();
} public static string StrSYH(string word)//具体方法3
{
return "\"" + word+ "\"";
} }

从上面可以看出其实,代码还是不少,继续改进为: (使用匿名函数) 方法只执行一次是时考虑使用  (匿名函数当做参数传递)

 public delegate string DelProStr(string word); //DelProStr 委托名称
class Program
{
static void Main(string[] args)
{
//三个需求
//1、将一个字符串数组中每个元素都转换成大写
//2、将一个字符串数组中每个元素都转换成小写
//3、将一个字符串数组中每个元素两边都加上 双引号
string[] words = { "abCDefG", "HIJKlmnOP", "QRsTuvW", "XyZ" }; ProStr(words, delegate (string word)
{
// return "\"" + word + "\"";
//return word.ToUpper();//大写
return word.ToLower();//小写
});
for (int i = ; i < words.Length; i++)
{
Console.WriteLine(words[i]);
}
Console.ReadKey();
} public static void ProStr(string[] word, DelProStr del)//del 委托变量
{
for (int i = ; i < word.Length; i++)
{
word[i] = del(word[i]);//委托调用
}
} }

现在我们可能会产生一种疑问匿名函数是啥?该咋用?

1.匿名函数概念?

简而言之,匿名函数就是没有函数名称的函数(方法)。

2.该咋用?

A,B函数需要在满足某种特定条件下才去执行,因此我们不必要去为功能单独添加函数A,B,我们可以使用匿名函数来直接实现  。

使用格式: 委托变量=delegate(参数){需要执行的A,B方法体}  参数:是根据委托创建的具体方法需要的参数类型

还有一种与匿名函数相似的方法,但是比匿名函数高级的写法为lambda表达式  :没有函数名称与delegate的函数

 public delegate string DelProStr(string word);
class Program
{
static void Main(string[] args)
{
//三个需求
//1、将一个字符串数组中每个元素都转换成大写
//2、将一个字符串数组中每个元素都转换成小写
//3、将一个字符串数组中每个元素两边都加上 双引号
string[] words = { "abCDefG", "HIJKlmnOP", "QRsTuvW", "XyZ" }; ProStr(words, (string word)=>
{
return word.ToLower();//小写
});//使用lambda表达式的写法
for (int i = ; i < words.Length; i++)
{
Console.WriteLine(words[i]);
}
Console.ReadKey();
} public static void ProStr(string[] word, DelProStr del)
{
for (int i = ; i < word.Length; i++)
{
word[i] = del(word[i]);
}
} }
“Lambda 表达式”是一个匿名函数,
所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x times x”。 第二章,通过另外的例子总结委托、Lambda表达式和匿名方法的关系。
1.委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的调用可以像其他任何方法一样,具有参数和返回值
2.C# 2.0 版引入了 匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。
匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数。
“匿名方法”就是没有名称的方法。匿名方法通常用于将代码块作为委托参数进行传递。
3.“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。
所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。该 Lambda 运算符的左边是输入参数(如果有),
右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x times x”。 例如:使用三种方式实现两个数的相加。
delegate int AddDelegate(int a, int b);//委托类
class AddClass
{
int a;
int b;
public AddClass(int a, int b)//构造函数
{
this.a = a;
this.b = b;
}
///////////////////////////////////三个具体的方法
private int Add1(int a, int b)
{
return a + b;
} public int Add2()
{
AddDelegate myAdd = new AddDelegate(Add1);//使用new 关键字创建对象必须要先有方法与之绑定
//<=> AddDelegate myAdd=Add1 return myAdd(a, b);
} public int Addition3()
{
AddDelegate myAdd = delegate(int a, int b) { return a + b; }; //匿名方法 return myAdd(a, b);
}
public int Addition3()
{
AddDelegate myAdd = (a, b) => a + b; //Lambda表达式 return myAdd(a, b);
}
}
特例:   

(1)Func委托   是系统已经定义好的委托    0~16个参数,有返回值

(1.1)无参数带返回值    Func<T> fun=()=>{方法体带返回值}

(1.2)有参数带返回值  Func<T,TResult>  fun=()=>{方法体带返回值}    TResult为方法的返回类型。

Func委托有5个重载形式,区别仅在于它所指向的方法的签名的参数个数,分别如下:

Func<TResult>

Func<T,TResult>

Func<T1,T2,TResult>

unc<T1,T2,T3,TResult>

Func<T1,T2,T3,T4,TResult>
其中T,T1,..T4是委托指向的方法的参数的类型,TResult为方法的返回类型。

如何使用Func委托?

首先,需要一个具体的方法。

其次,使用Func委托定义变量并关联方法

最后,委托调用

(2)Action委托  是系统已经定义好的委托    0~16个参数,无返回值

(2.1)Action action=(参数可选)=>{方法体中无返回值}

(2.2)Action<T>  act=(参数可选)=>{方法体中无返回值}

Action委托也有16个重载形式,分别如下:
Action Action<T> Action<T1,T2> Action<T1,T2,T3>
..
Action<T1,T2,T3,T4..>
其中T,T1,..T4...是委托指向的方法的参数的类型。
从上面的委托形式我们就可以分析出来,Func和Action委托的唯一区别在于Func要有返回值, Action没有返回值。

第三章: 事件

1.事件的由来:

实际应用中,通常都是 Program在一个类中,三个具体方法在另外的类中。但并不是所有的字段都应该声明成public,合适的做法是应该public的时候public,应该private的时候private。对于委托对象有些时候需要public有些时候需要private。当把委托对象(DelProStr)声明为private时,会怎么样呢???有点小无语。因为声明委托的目的就是为了把它暴露在类的客户端进行方法的注册,你把它声明为private了,客户端对它根本就不可见,那它还有什么用?

再看看把委托对象(DelProStr)声明为 public 会怎样?结果就是:在客户端可以对它进行随意的赋值等操作,严重破坏对象的封装性。

现在我们想想,如果DelProStr不是一个委托类型,而是一个string类型,你会怎么做?答案是使用属性对字段进行封装。于是,Event出场了,它封装了委托类型的变量,使得:在类的内部,不管你声明它是public还是protected,它总是private的。在类的外部,注册“+=”和注销“-=”的访问限定符与你在声明事件时使用的访问符相同。

2.什么是事件?

事件其实没什么不好理解的,声明一个事件不过类似于声明一个进行了封装的委托类型的变量而已。

  public  DelProStr    delProStr;//delProStr这是一个委托变量

public  event DelProStr  eventDelProStr;//eventDelProStr  事件:委托变量关键字+event

委托:是一种类型       (形如Person类)

事件:是委托的一个实例    (形如  由Person类实例化后的对象变量man)  Person  man=new Person(); 

3.怎么使用事件??

前提是要声明一个委托

首先,声明一个事件(在委托的基础上才能实现)                              :实为对委托的封装

然后判断eventDelProStr是否为空 :只有在(动作)事件注册后并判断是否有事件然后才能执行。

if(eventDelProStr!=null)

{

eventDelProStr.Invoke();//执行注册的(动作)  而不是方法  

}

最后,(外界)注册(动作)事件    (通过“+=”和 “-+”) (跟委托与方法关联的步骤一样)

 委托与事件的区别:
(1)事件不允许外面直接对事件赋值方法 委托在外界赋值后会导致赋值之前的注册会失效
(2)事件不允许在外面直接调用事件 委托在外界调用会跳过委托方法(会重置关联的方法使之变为null)
 学习地址:http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx    (C# 中的委托和事件)

委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结的更多相关文章

  1. Lambda表达式与匿名方法

    在C#2中,由于有了方法组,匿名方法,类型的协变和抗变,使得运用delegate变得很容易,在注册事件时代码变得简单易读,但是在C# 2中,代码仍然有点臃肿,大块的匿名方法会降低代码的可读性,一般我们 ...

  2. 匿名函数:Lambda表达式和匿名方法

    匿名函数一个"内联"语句或表达式,可在需要委托类型的任何地方使用.可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. 共有两种匿名函数: Lamb ...

  3. Effective Java 第三版——42.lambda表达式优于匿名类

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. kotlin之lambda表达式和匿名函数

    lambda表达式,称为匿名函数,是一种函数字面值,也就是没有声明的函数,但可以作为表达式传递出去. 函数类型: 对于接受另一个函数的作为自己的参数,必须针对这个参数指定一个函数的类型如 fun &l ...

  5. Python函数与lambda 表达式(匿名函数)

    Python函数 一.函数的作用 函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段 函数能提高应用的模块性和代码的重复利用率 python 内置函数:https://docs.pytho ...

  6. Lambda 表达式-即匿名函数

    拉姆达值(Lambda),希腊字母表示为Λ,指与真空的空间有关的能量或暗能量.   代表转换的常量.或者转换本身.   Lambda 表达式 Lambda 表达式”是一个匿名函数,可以包含表达式和语句 ...

  7. C++11 Lambda表达式(匿名函数)

    http://www.cnblogs.com/RainyBear/p/5733399.html http://blog.163.com/lvan100@yeah/blog/static/6811721 ...

  8. lambda表达式、匿名函数

    lambda表达式是函数式编程中的匿名函数语法规范. In computer programming, an anonymous function (function literal, lambda ...

  9. C++11 — lambda表达式(匿名函数)

    C++11中lambda表达式的基本语法格式为: [capture](parameters) -> return_type { /* ... */ } 其中 [] 内为外部变量的传递方式: [] ...

随机推荐

  1. POI的简单使用

    一:简介 利用POI工具可以导出word,excel,ppt等office文件 二:程序代码示例 package com.wang.test; import java.io.File; import ...

  2. CentOS7使用打开关闭防火墙与端口

    systemctl是CentOS7的服务管理工具中主要的工具,它融合之前service和chkconfig的功能于一体. 启动一个服务:systemctl start firewalld.servic ...

  3. 时间操作(JavaScript版)—年月日三级联动(默认显示系统时间)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangshuxuncom/article/details/35263317         这个功能 ...

  4. C#中Task的使用简单总结

    Task在并行计算中的作用很凸显,但是他的使用却有点小复杂,下面是任务的一些基本使用说明(转载与总结于多篇文章) 简单点说说吧! 创建 Task 创建Task有两种方式,一种是使用构造函数创建,另一种 ...

  5. Java调用.NET webservice方法的几种方式

    最近做项目,涉及到web-service调用,现学了一个星期,现简单的做一个小结.下面实现的是对传喜物流系统(http://vip.cxcod.com/PodApi/GetPodStr.asmx?ws ...

  6. spring boot中,jar包、war包的区别

    jar包.war包 比较(表格) 项目 jar包 war包 在开发调试完成之后,可以将应用打成JAR包的形式,可以直接使用Maven插件的package命令,最终会形成一个可运行的 JAR包.我们使用 ...

  7. window.open 和 location.href 区别

    window.open():可以在一个网站上打开另外的一个网站的地址 window.location():只能在一个网站中打开本网站的网页

  8. mysql常用语法操作

    一.用户管理: 1.新建用户: >CREATE USER name IDENTIFIED BY 'ssapdrow'; 2.更改密码: >SET PASSWORD FOR name=PAS ...

  9. C#继承基本控件实现自定义控件 (转帖)

    自定义控件分三类: 1.复合控件:基本控件组合而成.继承自UserControl 2.扩展控件:继承基本控件,扩展一些属性与事件.比如继承Button 3.自定义控件:直接继承自Control 第一种 ...

  10. 启动servlet报错:The servlets named [DemoServlet] and [main.java.com.wlf.demo.servlet.DemoServlet] are both mapped to the url-pattern [/hello] which is not permitted

    先看具体错误日志: [2019-04-26 09:29:25,484] Artifact demo-servlet:war: Artifact is being deployed, please wa ...