C#委托

C#委托


++委托的定义

++++delegate(委托)是表示将方法作为参数传递给其他方法。 委托类似于函数指针,但与函数指针不同的是,委托是面向对象的,类型安全的和保险的。 委托既能引用静态方法,也能引用实例方法。


++委托的引入

++++在引入委托之前,我们先来看一段代码:

 

class HelloWorld{

    public void GreetPeople(string name){

        EnglishGreeting(name);

}

public void EnglishGreeting(string name){

    Console.WriteLine(Morning, + name);

}

}

 

++++假设以后这段代码需要全球化,加入中国人问候的方法。

--首先需要添加中国人问候的方法修改代码如下:

    public void ChineseGreeting(string name){

        Console.WriteLine(早上好, + name);

}

 

++++然后添加枚举来区分语言,修改代码如下:

enum Language{

    English,

    Chinese

}

 

++++为调用ChineseGreeting()这个方法我们同样需要修改GreetingPeople()这个方法:

public void GreetPeople(string name,Language language){

    if(language == Language.Chinese){

        ChineseGreeting(name);

}else if(language == Language.English){

    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){

    Console.WriteLine(Morning, + name);

}

public void ChineseGreeting(string name){

    Console.WriteLine(早上好, + 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){

          Console.WriteLine(hello, + name);

}

public static void ChineseGreeting(string name){

    Console.WriteLine(你好, + name);

}

public void GreetingPeole(string name,GreetingDelegate method){

    method(name);

}

}

--测试运行代码

  class Program{

      static void Main(string[] args){

          HelloWorld hw = new HelloWorld();

          hw.GreetingPeople(中国人, HelloWorld.ChineseGreeting);

          Console.ReadKey();

}

}


++总结

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


++将方法绑定到委托

 

++++既然委托同string都是类型,那我们也可以利用委托声明类似name这样的委托变量。 修改代码如下:

class Program{

    static void Main(string[] args){

        HelloWorld hw = new HelloWorld();

        HelloWorld.GreetingDelegate delegate1, delegate2;

        delegate1 = HelloWorld.EnglishGreeting;

        delegate2 = HelloWorld.ChineseGreeting;

        hw.GreetingPeople(中国人, delegate1);

        hw.GreetingPeople(yanlz, delegate2);

        Console.ReadKey();

}

}

 

++++如你所料,这样是没有问题的。 委托不同于string的一个特征: 可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。 如下:

HelloWorld.GreetingDelegate delegate1;

delegate1 = HelloWorld.EnglishGreeting;

delegate1 += HelloWorld.ChineseGreeting;

hw.GreetingPeople(yanlz, delegate1);

 

++++实际上我们可以绕过调用GreetingPeople(),通过委托来直接调用EnglishGreetingChineseGreeting

HelloWorld.GreetingDelegate delegate1;

delegate1 = HelloWorld.EnglishGreeting;

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(){

        Console.WriteLine(按钮被点击了!~);

}

}

 

Click dele1;

dele1 = Button.ClickFinished;

dele1();

 

运行程序,输出按钮被点击了!~  这属于我们常规的委托,绑定方法。

    

++++利用匿名函数实现,修改代码如下:

Click click = delegate(){

    Console.WriteLine(按钮被点击了2222);

}

click();

运行程序,输出  按钮被点击了2222


++总结

++++以前我们都是先声明委托,在赋值对应的方法或者直接new关联一个方法。 实际上匿名方法的出现就是在初始化时内敛声明的方法,使得委托的语法更简洁


++C#中内置了三种委托方式

++++1Func委托

++++2Action委托

++++3Predicate委托


++Func委托

++++Func委托的5种类型

  --1delegate TResult Func<TResult>

  --2delegate TResult Func<T1, TResult>(T1 arg1)

  --3delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2)

  --4delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3)

  --5delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

++++Func委托类型说明:

  --1)只能委托无参但是有返回值的函数,TResult就是其返回类型。

  --2)只能委托具有一个传入参数,有返回值的函数,T1为一个传入参数,TResult为返回类型。

  --3)只能委托具有二个传入参数,有返回值的函数,T1T2为两个传入参数,TResult为返回类型。

  --4)和(5),以此类推。

++++Func委托总结

使用Func委托函数必须带有返回值,即TResult

Func<string> func = delegate(){

    return我是func<TResult>委托出来的结果;

};

string result = func();

Console.WriteLine(result);

--注: 这里为了演示func委托,直接用的匿名方法,我们同样可以为func委托绑定方法,这里不做演示。

 

++++Func委托总结(第二种func类型演示)

Func<string, string> func2= delegate(strings){

    returns.ToLower();

}

string result2 = func2(HELLO);

Console.WriteLine(result2)

--注: 这里为了演示func委托,直接用的匿名方法,我们同样可以为func委托绑定方法,这里不做演示。

++++Func委托总结(第三种func类型演示)

Func<stirng, string, string> func3= delegate(string value1,string value2){

    return value1 +  + value2;

}

Console.WriteLine(func3(我是,Func<T1, T2, TResult>委托出来的结果));

--注: 这里为了演示func委托,直接用的匿名方法,我们同样可以为func委托绑定方法,这里不做演示。


++Action委托

++++Action委托的5种类型

-- 1delegate void Action();  无参,无返回值

-- 2delegate void Action<T>(T1 arg1);

-- 3delegate void Action<T1, T2>(T1 arg1, T2 arg2);

-- 4delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);

-- 5delegate 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) => {

    Console.WriteLine(这是一个用Lambda表达式委托,参数为 + x);

}

d1(严立钻); //调用

 

delegate3 d3 = (x, y) => {

    Console.WriteLine(这是一个用Lambda表达式委托带两个参数,和返回值);

    returnx + y;

};

Console.WriteLine(d3(1, 2));

++++Lambda表达式案例演示

下面我们利用lambda表达式,实现一个小功能。假设存在某个课程集合,我们需要知道这个集中中包含哪几个课程,哪几个是vip课程,利用lambda表达式实现。




#立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

++立钻哥哥推荐的拓展学习链接(Link_Url

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

++++C#事件https://blog.csdn.net/vrunsoftyanlz/article/details/78631267

++++C#委托https://blog.csdn.net/vrunsoftyanlz/article/details/78631183

++++C#集合https://blog.csdn.net/vrunsoftyanlz/article/details/78631175

++++C#泛型https://blog.csdn.net/vrunsoftyanlz/article/details/78631141

++++C#接口https://blog.csdn.net/vrunsoftyanlz/article/details/78631122

++++C#静态类https://blog.csdn.net/vrunsoftyanlz/article/details/78630979

++++C#中System.String类https://blog.csdn.net/vrunsoftyanlz/article/details/78630945

++++C#数据类型https://blog.csdn.net/vrunsoftyanlz/article/details/78630913

++++Unity3D默认的快捷键https://blog.csdn.net/vrunsoftyanlz/article/details/78630838

++++游戏相关缩写https://blog.csdn.net/vrunsoftyanlz/article/details/78630687

++++Unity引擎基础https://blog.csdn.net/vrunsoftyanlz/article/details/78881685

++++Unity面向组件开发https://blog.csdn.net/vrunsoftyanlz/article/details/78881752

++++Unity物理系统https://blog.csdn.net/vrunsoftyanlz/article/details/78881879

++++Unity2D平台开发https://blog.csdn.net/vrunsoftyanlz/article/details/78882034

++++UGUI基础https://blog.csdn.net/vrunsoftyanlz/article/details/78884693

++++UGUI进阶https://blog.csdn.net/vrunsoftyanlz/article/details/78884882

++++UGUI综合https://blog.csdn.net/vrunsoftyanlz/article/details/78885013

++++Unity动画系统基础https://blog.csdn.net/vrunsoftyanlz/article/details/78886068

++++Unity动画系统进阶https://blog.csdn.net/vrunsoftyanlz/article/details/78886198

++++Navigation导航系统https://blog.csdn.net/vrunsoftyanlz/article/details/78886281

++++Unity特效渲染https://blog.csdn.net/vrunsoftyanlz/article/details/78886403

++++Unity数据存储https://blog.csdn.net/vrunsoftyanlz/article/details/79251273

++++Unity中Sqlite数据库https://blog.csdn.net/vrunsoftyanlz/article/details/79254162

++++WWW类和协程https://blog.csdn.net/vrunsoftyanlz/article/details/79254559

++++Unity网络https://blog.csdn.net/vrunsoftyanlz/article/details/79254902

++++设计模式简单整理https://blog.csdn.net/vrunsoftyanlz/article/details/79839641

++++U3D小项目参考https://blog.csdn.net/vrunsoftyanlz/article/details/80141811

++++UML类图https://blog.csdn.net/vrunsoftyanlz/article/details/80289461

++++Unity知识点0001https://blog.csdn.net/vrunsoftyanlz/article/details/80302012

++++U3D_Shader编程(第一篇:快速入门篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80372071

++++U3D_Shader编程(第二篇:基础夯实篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80372628

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/


--_--VRunSoft:lovezuanzuan--_--

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值