您当前的位置: 首页 >  c#

Peter_Gao_

暂无认证

  • 1浏览

    0关注

    621博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C#基础-委托(Delegate)

Peter_Gao_ 发布时间:2020-02-21 17:17:51 ,浏览量:1

关于事件:https://blog.csdn.net/qq_42672770/article/details/104436524

委托与匿名方法、Lambda表达式 : https://blog.csdn.net/qq_42672770/article/details/111941851

最简版:

什么是委托: 方法的指针。是存储方法的变量。是一个类。

怎么用:两种:自定义委托 、 系统提供的委托类action 和 func

一. 自定义委托:

1.声明委托类型

2.实例化委托变量

3.定义一个与委托(参数和返回值)签名相同的方法。

4. 把方法赋值给委托变量

5. 调用执行委托

这里是一个无参无返回值的最简单的自定义委托例子:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestDelegate : MonoBehaviour
{
    //定义委托类
    public delegate void MyDelegateClass();

    //实例化委托类,即声明一个委托类型的变量
    public MyDelegateClass myDelegateTest;

    //声明一个将来要调用的普通方法,注意必须跟委托的参数和返回值签名相同
    private void GoTest()
    {
        Debug.Log("111");
    }

    private void Start()
    {
        //把普通方法赋值给委托变量
        myDelegateTest = GoTest;

        //调用存有方法的委托变量,也就等同与调用了前面定义的那个普通方法
        myDelegateTest();
    }
}

当然,也可以用Lambda表达式的写法来替代普通函数

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestDelegate : MonoBehaviour
{
    //定义委托类
    public delegate void MyDelegateClass();

    //实例化委托类,即声明一个委托类型的变量
    public MyDelegateClass myDelegateTest;

    //声明一个将来要调用的普通方法,注意必须跟委托的参数和返回值签名相同
    //private void GoTest()
    //{
    //    Debug.Log("111");
    //}

    private void Start()
    {
        //把普通方法赋值给委托变量
        //myDelegateTest = GoTest;
        myDelegateTest = () =>
        {
            Debug.Log("111");
        }; 

        //调用存有方法的委托变量,也就等同与调用了前面定义的那个普通方法
        myDelegateTest();
    }
}

二、Action C#自带的委托类,可多参、无返回值。

这个类型可以直接拿来实例化出来一个委托类型的委托变量。

比自定义委托只少了一个类型声明步骤。

using System; //注意 Action是系统内置的类型
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAction : MonoBehaviour
{
    //声明一个Action类型的变量
    public Action myAction;

    //一个普通方法
    private void GoTest()
    {
        Debug.Log("222");
    }

    void Start()
    {
        //把普通方法赋值给前面定义好的Action变量
        myAction = GoTest;
        //调用这个存有方法的变量,也即调用了这个普通方法
        myAction();
    }
}
三、Func C#自带的有返回值的委托类型

Func和Action作用几乎是一样的,但是Func有返回值!Action是没有返回值的!示例如下:

 

四、自定义委托的实际案例:

下面是一个网游的新手任务模块使用委托进行数据传递的示例:

有两个类: 一个是管理类NewbieTaskManager.cs,一个是UI展示类UINewbieTask.cs

调用委托的处理方法:当收到上行服务器返信后,把反信数据传给委托,再传给普通方法进行处理。

在另一个UI展示类中,把普通方法 InitData注册赋值给Manager中定义的委托变量,一旦Manager管理器中反信调用了委托,则这里UI类的普通InitData方法也会被调用执行。

以下是太长不看版:

是什么:顾名思义,委托别人帮你办事。实质是把方法当作参数进行传递。

用在哪里:委托(Delegate)特别用于实现事件和回调方法。

怎么用:三要素:1.发布者类:声明、实例化委托(事件), 2. 响应者类、订阅响应,3、处理响应

用vs新建一个 C# 控制台文件.

1. 发布者类,声明并实例化一个委托。(来,帮姐办点事!)

public class GoodGirl {     public delegate void HelpGirlEventHandler();

    public static HelpGirlEventHandler HelpGirlEvent; 

    void OnGUI()

    {

            public void HelpGirlEvent ()

           {  

                Console.WriteLine("来,帮姐办个事");                 Console.ReadKey() ;            } 

    }

 }

2. 响应者类,订阅响应

  public class BadGuy   {

      GoodGirl.HelpGirlEvent += FixPc;      

      GoodGirl.HelpGirlEvent += FixPhone;  

3. 响应者处理响应         public static void FixPC()         {             Console.WriteLine("用工具5分钟修好了电脑");         }

        public static void FixPhone()         {             Console.WriteLine("用工具10分钟修好了手机");         }     }

委托用的最多的场景是回调方法。

委托是C#实现回调函数的一种机制。可能有人会问了,回调函数是个啥???

举个回调例子:

老板(委托方), 委托HR小姐姐(被委托方)负责面试和培训,小姐姐能做的工作就是回调函数的作用。

一旦有了满足条件(比如约好时间),小姐姐就会面试(触发回调函数),

一旦有了满足条件(比如新人入职), 小姐姐就会进行培训(触发回调函数)。

再一个例子:

委托 printString 可用于引用带有一个字符串作为输入的方法,并不返回任何东西。

我们使用这个委托来调用两个方法,第一个把字符串打印到控制台,第二个把字符串打印到文件:

using System; using System.IO; namespace DelegateAppl {    class PrintString    {       static FileStream fs;       static StreamWriter sw;       // 1.委托方发起抽象的委托声明       public delegate void printString(string s);

      // 2. 委托方实例化具体的委托。并把被委托方拥有的方法作为参数传入委托。       public static void sendString(printString ps)       {          ps("Hello World");       }       static void Main(string[] args)       {          printString ps1 = new printString(WriteToScreen);          printString ps2 = new printString(WriteToFile);          sendString(ps1);          sendString(ps2);          Console.ReadKey();       }       // 3. 被委托方拥有输出到控制台的方法       public static void WriteToScreen(string str)       {          Console.WriteLine("The String is: {0}", str);       }       //4. 被委托方还拥有写入到文件的方法       public static void WriteToFile(string s)       {          fs = new FileStream("c:\\message.txt", FileMode.Append, FileAccess.Write);          sw = new StreamWriter(fs);          sw.WriteLine(s);          sw.Flush();          sw.Close();          fs.Close();       }    } }

设计模式中的观察者模式。 被观察对象中维护了一个观察者列表,这些观察者会对被观察者某个“动作”,即事件,做出各自不同的反映。 常见的例子如下: 某一场景下有主人,猫,狗3个对象。 当主人“打开门”后,猫“跑开了”,狗“叫了”。 整个过程中,主人就是被观察对象,猫和狗都是观察者。 一旦主人触发“打开门”这个事件的话,猫狗做出不同的反映,猫“跑开了”,狗“叫了”

总结:

委托实际上是类(一个貌似函数一样的类),我们已经使用函数指针很多年了——函数指针也被称为过程类型,但是它们的实现都不是类。它们是单独的函数指针的简单实例。委托是包含这些功能的类,委托类通过保留的列表来确定某些事物是否已经指派给了委托,这种算法可以理解为:“对于内部列表中的每一个回调函数,都调用函数”。委托除了支持回调函数外,还可以通过该列表来实现多播(委托链)。

说白了,就是我们把一批具有相同特征的方法,通过建立与具有同样相同特征的委托的一个实例来进行传递,以使其它地方能对这些方法进行调用。即把方法当作参数进行传递。

委托从字面上理解就是一种代理,类似于房屋中介,由租房人委托中介为其租赁房屋。 在 C# 语言中,委托则委托某个方法来实现具体的功能。 委托是一种引用类型,虽然在定义委托时与方法有些相似,但不能将其称为方法。 委托在使用时遵循三步走的原则,即定义声明委托、实例化委托以及调用委托。 从数据结构来讲,委托是和类一样是一种用户自定义类型。 委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。 调用委托的时候,委托包含的所有方法将被执行。 委托是 C# 语言中的一个特色,通常将委托分为命名方法委托、多播委托、匿名委托,其中命名方法委托是使用最多的一种委托。

委托就是我们把一批具有相同特征的方法,通过建立与具有同样相同特征的委托的一个实例来进行传递,以使其它地方能对这些方法进行调用。即把方法当作参数进行传递

事件委托的好处是,别人给你开放入口,具体实现自己定义。

通过理解Button.Click事件的整个过程就会明白委托和事件了,不过得看下自定义控件,页面生命周期,回发,观察者模式,假以时日,委托和事件也就会一点点明白了。 ASP.NET WEBFORM中很多用到事件的地方,看看还是有帮助的。 很多ASP.NET程序员,觉得拖控件被人家看不起,还没弄懂委托和事件,就直接转MVC,有点可惜

委托就是对一个方法映射,把方法名当参数来传递,类似JS中的在某个function的参数中把另一个function的名称当参数来传递。

1. C#的委托等同于C++的函数指针 。可以 从 C++函数指针反过来理解C#委托。 2. 委托应用于“同步调用”的场景,如一个有声阅读器,打开记事本(1)并开始阅读(2),这是两个方法,但这时,我想 调用打开的方法时,同时调阅读,这时候委托就来了,把阅读这个方法作为参数传给“打开记事本”的方法。

微软提供了Action和Fun。。。其实基本上已经没必要自己写委托了

委托的主要好处是可以把方法作为参数/属性来赋值或传递。事件是委托的一种具体应用。委托可以理解为一种接口,具体的方法实现这个接口,在开发阶段只需要关心委托的定义就可以调用,而不用关心它如何实现的或者在哪里实现的。

Action

using System; /// /// Action 是一个没有返回值,但是可以有参数的委托类型 /// Action 最多可以有16个参数 /// namespace Action委托类型 {     class MainClass     {         //------------无参无返回值方法------------------------------         private static void ActionTest()         {         Console.WriteLine ("委托一个无参无返回值方法");         }           //------------参数是string,无返回值方法---------------------         private static void ActionTest2(string str)         {             Console.WriteLine ("输出一个参数是:" + str + " 的方法");         }         public static void Main (string[] args)         {             //----------------------------------------------------------               // Action是系统预定义的一个无参数,无返回值委托类型             Action test = ActionTest;             //  调用Action的委托实例             test();               //----------------------------------------------------------               // Action指向一个,参数是string,无返回值类型的委托             Action test2 = ActionTest2;             test2("sea");               //----------------------------------------------------------             }     } }

参考链接:

https://blog.csdn.net/wnvalentin/article/details/81840339

https://www.cnblogs.com/jixiaosa/p/10687068.html

https://www.cnblogs.com/qcst123/p/11575557.html

http://c.biancheng.net/view/2932.html

https://blog.csdn.net/weixin_34072458/article/details/85652130

https://www.cnblogs.com/stwyhm/archive/2006/08/11/474235.html

https://bbs.csdn.net/topics/390751609/

关注
打赏
1664521772
查看更多评论
立即登录/注册

微信扫码登录

0.0396s