C#委托
++委托的定义
++++delegate(委托)是表示将方法作为参数传递给其他方法。 委托类似于函数指针,但与函数指针不同的是,委托是面向对象的,类型安全的和保险的。 委托既能引用静态方法,也能引用实例方法。
++委托的引入
++++在引入委托之前,我们先来看一段代码:
class HelloWorld{
public void GreetPeople(string name){
EnglishGreeting(name);
}
public void EnglishGreeting(string name){
(“Morning,” + name);
}
}
++++假设以后这段代码需要全球化,加入中国人问候的方法。
--首先需要添加中国人问候的方法修改代码如下:
public void ChineseGreeting(string name){
(“早上好”, + name);
}
++++然后添加枚举来区分语言,修改代码如下:
enum Language{
English,
Chinese
}
++++为调用ChineseGreeting()这个方法我们同样需要修改GreetingPeople()这个方法:
public void GreetPeople(string name,Language language){
if(language == ){
ChineseGreeting(name);
}else if(language == ){
EnglishGreeting(name);
}
}
++++最终代码如下:
class HelloWorld{
public void GreetPeople(string name,Language language){
//这里的Language为上文提到的枚举
if(language == Language.Chinese){
ChineseGreeting(name);
}else if(language ==Language.English){
EnglishGreeting(name);
}
}
public void EnglishGreeting(string name){
(“Morning,” + name);
}
public void ChineseGreeting(string name){
(“早上好”, + name);
}
}
++++这个小程序真的做好了吗?
--上面的方案大家很容易想到。 利用枚举去扩展语言。 但是这个解决方案 扩展性很差。 假如日后我们需要加入 日语,韩语,拉丁语等。 那我们不得不反复修改 枚举添加新的语言 和GreetingPeople()内部利用if ... else或者switch分支去根据传入的参数,判断调用某个语言进行问好。
++声明并定义委托
class HelloWorld{
//声明委托
public delegate void GreetingDelegate(string name);
......
}
-- void表示委托代表的方法的返回值类型。
-- string name表示委托代表的方法的参数类型。
++++有了委托之后我们可以修改GreetPeople(string name, **** method),代码如下:
public void GreetingPeople(string name,GreetingDelegate method){
//委托的调用方法同方法调用一样
method(name);
}
--这里的GreetingDelegate就是method的类型,或者叫类。 需要注意的是委托的声明方式和类却完全不同。 实际上,委托在编译的时候确实会编译成类。因为Delegate是一个类,所以在任何可以声明类的地方都可以声明委托。
++利用委托实现最终代码效果
class HelloWorld{
public delegate void GreetingDelegate(string name);
public static void EnglishGreeting(string name){
(“hello,” + name);
}
public static void ChineseGreeting(string name){
(“你好,” + name);
}
public void GreetingPeole(string name,GreetingDelegate method){
method(name);
}
}
--测试运行代码
class Program{
static void Main(string[] args){
HelloWorld hw = new HelloWorld();
(“中国人”, );
();
}
}
++总结
++++委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用 If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
++将方法绑定到委托
++++既然委托同string都是类型,那我们也可以利用委托声明类似name这样的委托变量。 修改代码如下:
class Program{
static void Main(string[] args){
HelloWorld hw = new HelloWorld();
delegate1, delegate2;
delegate1 = ;
delegate2 = ;
hw.GreetingPeople(“中国人”, delegate1);
hw.GreetingPeople(“yanlz”, delegate2);
();
}
}
++++如你所料,这样是没有问题的。 委托不同于string的一个特征: 可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。 如下:
delegate1;
delegate1 = ;
delegate1 += ;
(“yanlz”, delegate1);
++++实际上我们可以绕过调用GreetingPeople(),通过委托来直接调用EnglishGreeting和ChineseGreeting:
delegate1;
delegate1 = ;
delegate1(“yanlz”);
++++委托绑定方法时需要注意(多播委托), 注意这里,第一次用的“=”,是赋值的语法; 第二次,用的是“+=”,是绑定的语法。 如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。
++++既然委托属于类,我们也可以利用这一特性直接new出委托实例。
HelloWorld.GreetingDelegate delegate1 = new HelloWorl.GreetingDelegate(HelloWorld.ChineseGreeting);
delegate1 += HelloWorld.EnglishGreeting;
delegate1(“yanlz”);
++++既然给委托可以绑定一个方法,那么也应该有办法取消对方法的绑定。 很容易想到,利用-=,代码如下:
HelloWorld.GreetingDelegate delegate1 = new HelloWorld.GreetingDelegate(HelloWorld.ChineseGreeting);
delegate1 += HelloWorld.EnglishGreeting;
delegate1(“yanlz”);
delegate1 -= HelloWorld.ChineseGreeting;
delegate1(“yanlz”);
++匿名函数
++++我们利用委托实现一个按钮的点击事件
首先我们先声明一个类,代码如下:
public delegate void Click();
class Button{
public static void ClickFinished(){
(“按钮被点击了!~”);
}
}
Click dele1;
dele1 = Button.ClickFinished;
dele1();
运行程序,输出按钮被点击了!~ 这属于我们常规的委托,绑定方法。
++++利用匿名函数实现,修改代码如下:
Click click = delegate(){
(“按钮被点击了2222”);
}
click();
运行程序,输出 按钮被点击了2222
++总结
++++以前我们都是先声明委托,在赋值对应的方法或者直接new关联一个方法。 实际上匿名方法的出现就是在初始化时内敛声明的方法,使得委托的语法更简洁。
++C#中内置了三种委托方式
++++1、Func委托
++++2、Action委托
++++3、Predicate委托
++Func委托
++++Func委托的5种类型
--1、delegate TResult Func<TResult>
--2、delegate TResult Func<T1, TResult>(T1 arg1)
--3、delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2)
--4、delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3)
--5、delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
++++Func委托类型说明:
--(1)只能委托无参但是有返回值的函数,TResult就是其返回类型。
--(2)只能委托具有一个传入参数,有返回值的函数,T1为一个传入参数,TResult为返回类型。
--(3)只能委托具有二个传入参数,有返回值的函数,T1和T2为两个传入参数,TResult为返回类型。
--(4)和(5),以此类推。
++++Func委托总结
使用Func委托函数必须带有返回值,即TResult,
Func<string> func = delegate(){
return“我是func<TResult>委托出来的结果”;
};
string result = func();
(result);
--注: 这里为了演示func委托,直接用的匿名方法,我们同样可以为func委托绑定方法,这里不做演示。
++++Func委托总结(第二种func类型演示)
Func<string, string> func2= delegate(strings){
return();
}
string result2 = func2(“HELLO”);
(result2)
--注: 这里为了演示func委托,直接用的匿名方法,我们同样可以为func委托绑定方法,这里不做演示。
++++Func委托总结(第三种func类型演示)
Func<stirng, string, string> func3= delegate(string value1,string value2){
return value1 +“ ” + value2;
}
(func3(“我是”,“Func<T1, T2, TResult>委托出来的结果”));
--注: 这里为了演示func委托,直接用的匿名方法,我们同样可以为func委托绑定方法,这里不做演示。
++Action委托
++++Action委托的5种类型
-- 1、delegate void Action(); 无参,无返回值
-- 2、delegate void Action<T>(T1 arg1);
-- 3、delegate void Action<T1, T2>(T1 arg1, T2 arg2);
-- 4、delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
-- 5、delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
++++Action委托类型说明:
--(1)没有传入参数,也没有返回值,那么它适合代理那些无参,无返回值的函数。
--(2)有一个传入参数,无返回值,适合代理有参,无返回值的函数。
--(3)有两个传入参数,无返回值,适合代理有参*2,无返回值的函数
--(4)和(5),以此类推。
++委托总结
++++至于Predicate委托用的太少,这里不做叙述。
++++注意:Func委托和Action委托唯一的区别就是在于代理的方法(函数)有没有返回值。
--有返回值选择Func委托。
--没有返回值选择Action委托。
++++系统内置的两种委托绝大多数情况下可以适配任何情况,无需我们在写大量的代码去定义委托。但是不代表内置委托匹配任何情况。 根据特殊情况还需我们手动定义委托,切记。
++Lambda表达式
++++“Lambda”表达式是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。它可以包含表达式和语句,并且可以用创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内敛表达式。所有Lambda表达式都使用Lambda运算符=>,该运算符读作“goes to”。
++++Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块。
++++Lambda表达式是由.NET2.0演化而来的,也是LINQ的基础,熟练地掌握Lambda表达式能够快速地上手LINQ应用开发。
++++初识Lambda表达式
首先我们先声明一个类包含三个委托,代码如下:
class Lambda{
public delegate void delegate1(string name); //带参数的委托
public delegate void delegate2(); //不带参数的委托
public delegate int delegate3(int x,int y); //有返回值有参数的委托
}
++++Lambda表达式的使用
delegate1 d1 = (x) => {
(“这是一个用Lambda表达式委托,参数为” + x);
}
d1(“严立钻”); //调用
delegate3 d3 = (x, y) => {
(“这是一个用Lambda表达式委托带两个参数,和返回值”);
returnx + y;
};
(d3(1, 2));
++++Lambda表达式案例演示
下面我们利用lambda表达式,实现一个小功能。假设存在某个课程集合,我们需要知道这个集中中包含哪几个课程,哪几个是vip课程,利用lambda表达式实现。
#立钻哥哥Unity 学习空间: /VRunSoftYanlz/
++立钻哥哥推荐的拓展学习链接(Link_Url):
++++立钻哥哥Unity 学习空间: /VRunSoftYanlz/
++++C#事件:/vrunsoftyanlz/article/details/78631267
++++C#委托:/vrunsoftyanlz/article/details/78631183
++++C#集合:/vrunsoftyanlz/article/details/78631175
++++C#泛型:/vrunsoftyanlz/article/details/78631141
++++C#接口:/vrunsoftyanlz/article/details/78631122
++++C#静态类:/vrunsoftyanlz/article/details/78630979
++++C#中类:/vrunsoftyanlz/article/details/78630945
++++C#数据类型:/vrunsoftyanlz/article/details/78630913
++++Unity3D默认的快捷键:/vrunsoftyanlz/article/details/78630838
++++游戏相关缩写:/vrunsoftyanlz/article/details/78630687
++++Unity引擎基础:/vrunsoftyanlz/article/details/78881685
++++Unity面向组件开发:/vrunsoftyanlz/article/details/78881752
++++Unity物理系统:/vrunsoftyanlz/article/details/78881879
++++Unity2D平台开发:/vrunsoftyanlz/article/details/78882034
++++UGUI基础:/vrunsoftyanlz/article/details/78884693
++++UGUI进阶:/vrunsoftyanlz/article/details/78884882
++++UGUI综合:/vrunsoftyanlz/article/details/78885013
++++Unity动画系统基础:/vrunsoftyanlz/article/details/78886068
++++Unity动画系统进阶:/vrunsoftyanlz/article/details/78886198
++++Navigation导航系统:/vrunsoftyanlz/article/details/78886281
++++Unity特效渲染:/vrunsoftyanlz/article/details/78886403
++++Unity数据存储:/vrunsoftyanlz/article/details/79251273
++++Unity中Sqlite数据库:/vrunsoftyanlz/article/details/79254162
++++WWW类和协程:/vrunsoftyanlz/article/details/79254559
++++Unity网络:/vrunsoftyanlz/article/details/79254902
++++设计模式简单整理:/vrunsoftyanlz/article/details/79839641
++++U3D小项目参考:/vrunsoftyanlz/article/details/80141811
++++UML类图:/vrunsoftyanlz/article/details/80289461
++++Unity知识点0001:/vrunsoftyanlz/article/details/80302012
++++U3D_Shader编程(第一篇:快速入门篇):/vrunsoftyanlz/article/details/80372071
++++U3D_Shader编程(第二篇:基础夯实篇):/vrunsoftyanlz/article/details/80372628
++++立钻哥哥Unity 学习空间: /VRunSoftYanlz/
--_--VRunSoft:lovezuanzuan--_--