关于事件: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。。。其实基本上已经没必要自己写委托了
委托的主要好处是可以把方法作为参数/属性来赋值或传递。事件是委托的一种具体应用。委托可以理解为一种接口,具体的方法实现这个接口,在开发阶段只需要关心委托的定义就可以调用,而不用关心它如何实现的或者在哪里实现的。
Actionusing 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/