++框架知识点(YanlzFramework)
++++框架知识点是立钻哥哥在游戏框架整理中发现的一些知识点,这个是和框架有关的。
++++框架知识点主要是以框架开发为核心,梳理相关知识点,为接下来的框架实战夯实基础。
++框架知识点目录:
++++框架知识点001:Action
++++框架知识点002:delegate委托
++++框架知识点003:Event事件
++++框架知识点004:EventHandle
++++框架知识点005:Func
++++框架知识点006:Lambda表达式
++++框架知识点007:Type
++++框架知识点008:索引器(this[string key])
++框架知识点001:Action
++++Action委托:https://msdn.microsoft.com/zh-cn/library/system.action(v=vs.110).aspx
++++Action语法:public delegate void Action()
//立钻哥哥:Action(System.Core/System/Action)
using System;
namespace System{
public delegate void Action();
}
++++【Action委托】:封装一个方法,该方法不具有参数且不返回值。(命名空间:System)(程序集:mscorlib(位于mscorlib.dll))
++++Action委托可用于将方法作为参数传递而不用显式声明自定义委托。(封装的方法必须对应于此委托定义方法签名。这意味着,封装的方法必须具有任何参数,没有返回值。)(在C#中,该方法必须返回void。)()若要引用的方法没有参数并返回一个值,使用泛型Func<TResult>委托。)
++++当我们使用Action委托,则不需要显示定义一个委托封装的无参数的过程。
++++delegate void Action(); //立钻哥哥:无参,无返回值
++++delegate void Action<T>(T arg1); //有一个参数,无返回值
++++delegate void Action<T1, T2, T3, Tn>(T1 arg1, T2 arg2, T3 arg3, Tn argn) //多个参数
++++Action委托和Func委托唯一区别就在于代理的方法(函数)有没有返回值。(有返回值选择Func委托,没有返回值选择Action委托。)
++++系统内置的两种委托(Action和Func),绝大多数情况下可以适配任何情况,无需我们再写大量的代码去定义委托。(根据特殊情况还需我们手动定义委托。)
++Action示例引入(delegate显式定义=>Action=>匿名方法=>Lambda表达式)
++++立钻哥哥尝试利用四种方式来剖析引入Action概念。
//1、立钻哥哥:显式定义委托
using System;
public delegate void YanlzShowValue(); //立钻哥哥:显式定义委托
public class YanlzName{
private string instanceName;
public YanlzName(string name){
this.instanceName = name;
}
public void DisplayToWindow(){
Debug.Log(“立钻哥哥:DisplayToWindow()”);
}
}
public class YanlzTestDelegate{
public static void Main(){
YanlzName testName = new YanlzName(“立钻哥哥”);
YanlzShowValue showMethod = testName.DisplayToWindow;
showMethod();
}
}
//2、立钻哥哥:使用Action
using System;
//public delegate void YanlzShowValue(); //立钻哥哥:显式定义委托
public class YanlzName{
}
public class YanlzTestDelegate{
public static void Main(){
YanlzName testName = new YanlzName(“立钻哥哥”);
//YanlzShowValue showMethod = testName.DisplayToWindow; //显示定义委托
Action showMethod = testName.DisplayToWindow; //立钻哥哥:使用Action
showMethod();
}
}
//3、立钻哥哥:使用Action委托和C#中的匿名方法
using System;
//public delegate void YanlzShowValue(); //立钻哥哥:显式定义委托
public class YanlzName{
}
public class YanlzAnomymous{
public static void Main(){
YanlzName testName = new YanlzName(“立钻哥哥”);
//YanlzShowValue showMethod = testName.DisplayToWindow; //显示定义委托
//Action showMethod = testName.DisplayToWindow; //立钻哥哥:使用Action
Action showMethod = delegate(){ testName.DisplayToWindow(); } //匿名方法
showMethod();
}
}
//4、立钻哥哥:使用Action委托和lambda
using System;
//public delegate void YanlzShowValue(); //立钻哥哥:显式定义委托
public class YanlzName{
}
public class YanlzLambdaExpression{
public static void Main(){
YanlzName testName = new YanlzName(“立钻哥哥”);
//YanlzShowValue showMethod = testName.DisplayToWindow; //显示定义委托
//Action showMethod = testName.DisplayToWindow; //立钻哥哥:使用Action
//Action showMethod = delegate(){ testName.DisplayToWindow(); } //匿名方法
Action showMethod = ()=>testName.DisplayToWindow(); //使用Lambda表达式
showMethod();
}
}
++Action委托类型示例
++++Action是一个没有返回值,但是可以有参数的委托类型。(Action最多可以有16个参数。)
++++namesapce System{ public delegate void Action(); }
//立钻哥哥:利用一个简单示例加强对Action的理解
using System;
namespace YanlzAction{
class YanlzMainClass{
//立钻哥哥:无参无返回值方法
private static void ActionTest01(){
Debug.Log(“立钻哥哥:委托一个无参无返回值方法。”);
}
//立钻哥哥:参数是string,无返回值方法
private static void ActionTest02(string str){
Debug.Log(“立钻哥哥:输出一个参数是:” + str + “ 的方法”);
}
public static void Main(string[] args){
Action test01 = ActionTest01; //无参数,无返回值委托类型
test01(); //立钻哥哥:调用Action的委托实例
Action<string> test02 = ActionTest02; //参数是string,无返回值的委托
test02(“立钻哥哥”);
}
}
}
++Action
++++Action<T>委托:https://msdn.microsoft.com/zh-cn/library/018hxwa8(v=vs.110).aspx
++++Action<T>:封装一个方法,该方法只有一个参数并且不返回值。
++++public delegate void Action<in T>( T obj)
++++使用Action
//1、立钻哥哥:显式定义委托
using System;
delegate void YanlzDisplayMessage(string message); //立钻哥哥:显式定义委托
public class YanlzTestCustomDelegate{
public static void Main(){
YanlzDisplayMessage messageTarget; //立钻哥哥:显式定义委托
if(Environment.GetCommandLineArgs().Length > 1){
messageTarget = ShowWindowsMessage;
}else{
messageTarget = Console.WriteLine;
}
messageTarget(“立钻哥哥Tips: Love zuanzuan!”);
}
private static void ShowWindowsMessage(string message){
Debug.Log(message);
}
}
//2、立钻哥哥:使用Action
using System;
//delegate void YanlzDisplayMessage(string message); //立钻哥哥:显式定义委托
public class YanlzTestAction01{
public static void Main(){
//YanlzDisplayMessage messageTarget; //立钻哥哥:显式定义委托
Action<string> messageTarget; //立钻哥哥:使用Action
if(Environment.GetCommandLineArgs().Length > 1){
messageTarget = ShowWindowsMessage;
}else{
messageTarget = Console.WriteLine;
}
messageTarget(“立钻哥哥Tips: Love zuanzuan!”);
}
private static void ShowWindowsMessage(string message){
Debug.Log(message);
}
}
//3、立钻哥哥:使用Action
using System;
//delegate void YanlzDisplayMessage(string message); //立钻哥哥:显式定义委托
public class YanlzTestAnonMethod{
public static void Main(){
//YanlzDisplayMessage messageTarget; //立钻哥哥:显式定义委托
Action<string> messageTarget; //立钻哥哥:使用Action
if(Environment.GetCommandLineArgs().Length > 1){
//messageTarget = ShowWindowsMessage;
messageTarget = delegate(string s){ ShowWindowsMessage(s); } //匿名方法
}else{
//messageTarget = Console.WriteLine;
messageTarget = delegate(string s){ Console.WriteLine(s); } //匿名方法
}
messageTarget(“立钻哥哥Tips: Love zuanzuan!”);
}
private static void ShowWindowsMessage(string message){
Debug.Log(message);
}
}
//4、立钻哥哥:使用Action
using System;
//delegate void YanlzDisplayMessage(string message); //立钻哥哥:显式定义委托
public class YanlzTestAnonMethod{
public static void Main(){
//YanlzDisplayMessage messageTarget; //立钻哥哥:显式定义委托
Action<string> messageTarget; //立钻哥哥:使用Action
if(Environment.GetCommandLineArgs().Length > 1){
//messageTarget = ShowWindowsMessage;
//messageTarget = delegate(string s){ ShowWindowsMessage(s); } //匿名方法
messageTarget = s => ShowWindowMessage(s); //lambda表达式
}else{
//messageTarget = Console.WriteLine;
//messageTarget = delegate(string s){ Console.WriteLine(s); } //匿名方法
messageTarget = s => Console.WriteLine(s); //lambda表达式
}
messageTarget(“立钻哥哥Tips: Love zuanzuan!”);
}
private static void ShowWindowsMessage(string message){
Debug.Log(message);
}
}
++拓展:List
++++ForEach和ForEach
++++示例:利用Action
//立钻哥哥:在此示例中,Print方法用于向控制台显示列表的内容。(注意:该示例不显式声明Action
using System;
class YanlzProgram{
static void Main(){
List<string> names = new List<string>();
names.Add(“Yanlz”);
names.Add(“zuanzuan”);
names.Add(“wangjue”);
names.Add(“xiaojue”);
names.ForEach(YanlzPrint); //立钻哥哥:using the YanlzPrint method
//立钻哥哥:demonstrate the anonymous method
names.ForEach(delegate(string name){
Console.WriteLine(name);
});
}
private static void YanlzPrint(string s){
Console.WriteLine(s);
}
}
++Action
++++Action<T1, T2>:封装一个方法,该方法具有两个参数且不返回值。(若要引用的方法,具有两个参数并返回一个值,使用泛型Func<T1, T2, TResult>委托。)
++++public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2)
//1、立钻哥哥:显式声明委托
using System;
delegate void YanlzConcatStrings(string string1, string string2); //立钻哥哥:显式声明委托
public class YanlzTestDelegate{
public static void Main(){
string message1 = “立钻哥哥:The first line of a message.”;
string message2 = “立钻哥哥:The second line of a message.”;
YanlzConcatStrings myConcat; //立钻哥哥:显式声明委托
if(Environment.GetCommandLineArgs().Length > 1){
myConcat = MyWriteToFile;
}else{
myConcat = MyWriteToConsole;
}
myConcat(message1, message2);
}
private static void MyWriteToConsole(string string1, string string2){
Console.WriteLine(“立钻哥哥:{0}\n{1}”, string1, string2);
}
private static void MyWriteToFile(string string1, string string2){
StreamWriter writer = null;
try{
writer = new StreamWriter(Environment.GetCommandLineArgs()[1], false);
writer.WriteLine(“立钻哥哥:{0}\n{1}”, string1, string2);
}catch{
Console.WriteLine(“立钻哥哥:File write operation failed...”);
}finally{
if(writer != null){
writer.Close();
}
}
}
}
//2、立钻哥哥:使用Action
using System;
//delegate void YanlzConcatStrings(string string1, string string2); //立钻哥哥:显式声明委托
public class YanlzTestDelegate{
public static void Main(){
string message1 = “立钻哥哥:The first line of a message.”;
string message2 = “立钻哥哥:The second line of a message.”;
//YanlzConcatStrings myConcat; //立钻哥哥:显式声明委托
Action<string, string> myConcat; //立钻哥哥:使用Action
if(Environment.GetCommandLineArgs().Length > 1){
myConcat = MyWriteToFile;
}else{
myConcat = MyWriteToConsole;
}
myConcat(message1, message2);
}
}
//3、立钻哥哥:使用Action
using System;
//delegate void YanlzConcatStrings(string string1, string string2); //立钻哥哥:显式声明委托
public class YanlzTestDelegate{
public static void Main(){
string message1 = “立钻哥哥:The first line of a message.”;
string message2 = “立钻哥哥:The second line of a message.”;
//YanlzConcatStrings myConcat; //立钻哥哥:显式声明委托
Action<string, string> myConcat; //立钻哥哥:使用Action
if(Environment.GetCommandLineArgs().Length > 1){
//myConcat = MyWriteToFile;
myConcat = delegate(string s1, string s2){ MyWriteToFile(s1, s2); } //匿名函数
}else{
//myConcat = MyWriteToConsole;
myConcat = delegate(string s1, string s2){ MyWriteToConsole(s1, s2); }; //匿名
}
myConcat(message1, message2);
}
}
//4、立钻哥哥:使用Action
using System;
//delegate void YanlzConcatStrings(string string1, string string2); //立钻哥哥:显式声明委托
public class YanlzTestDelegate{
public static void Main(){
string message1 = “立钻哥哥:The first line of a message.”;
string message2 = “立钻哥哥:The second line of a message.”;
//YanlzConcatStrings myConcat; //立钻哥哥:显式声明委托
Action<string, string> myConcat; //立钻哥哥:使用Action
if(Environment.GetCommandLineArgs().Length > 1){
//myConcat = MyWriteToFile;
//myConcat = delegate(string s1, string s2){ MyWriteToFile(s1, s2); } //匿名函数
myConcat = (s1, s2)=>MyWriteToFile(s1, s2); //立钻哥哥:Lambda表达式
}else{
//myConcat = MyWriteToConsole;
//myConcat = delegate(string s1, string s2){ MyWriteToConsole(s1, s2); }; //匿名
myConcate = (s1, s2)=>MyWriteToConsole(s1, s2); //Lambda表达式
}
myConcat(message1, message2);
}
}
++示例:Action实际应用参考
//立钻哥哥:我们通过这个简单示例,熟悉一下Action及相关应用场景。
using System;
public class YanlzDemoAction{
public Action action;
public Action<int> action1;
public Action<int, string> action2;
public Action<List<int>> action3;
//立钻哥哥:不带参数
public void ActionDemo(){
if(null != action){
action();
}
}
//立钻哥哥:带一个参数
public void ActionDemo(int a){
if(action1 != null){
action1(a);
}
}
//立钻哥哥:带两个参数
public void ActionDemo(int a, string str){
if(action2 != null){
action2(a, str);
}
}
//立钻哥哥:带一个列表
public void ActionDemo(List<int> list){
if(action3 != null){
action3(list);
}
}
} //立钻哥哥:public class YanlzDemoAction
public class MyCSharpDemo : MonoBehaviour{
Action action;
//Use this for initialization
void Start(){
YanlzDemoAction demo = new YanlzDemoAction();
demo.action = TestAction;
demo.action1 = TestAction;
demo.action2 = TestAction;
demo.action3 = TestAction;
List<int> list = new List<int>(){ 10, 20, 30, 40 };
demo.ActionDemo();
demo.ActionDemo(20);
demo.ActionDemo(20, “立钻哥哥”);
demo.ActionDemo(list);
}
//Update is called once per frame
void Update(){
}
//立钻哥哥:不带参数
void TestAction(){
Debug.Log(“立钻哥哥:不带参数”);
}
//立钻哥哥:带一个参数
void TestAction(int a){
Debug.Log(“立钻哥哥:带一个参数 = ” + a);
}
//立钻哥哥:带2个参数
void TestAction(int a, string str){
Debug.Log(“立钻哥哥:带2个参数 a ” + a + “ str= ” + str);
}
//立钻哥哥:带一个列表
void TestAction(List<int> list){
Debug.Log(“立钻哥哥:带一个列表”);
for(int i = 0; i < list.Count; i++){
Debug.Log(“立钻哥哥:i=” + list[i]);
}
}
} //立钻哥哥:public class MyCSharpDemo : MonoBehaviour{}
++拓展:委托、事件、匿名方法、Action
++++立钻哥哥:我们通过此小节,来熟悉一下:委托、事件、匿名方法、Action等的相关知识点。
++++委托和事件的命名:
--委托以EventHandler作为后缀命名,例如:SalesOutEventHandler。
--事件以其对应的委托类型,去掉EventHandler后缀,并加上On前缀构成。
--例如:对于StateChangeEventHandler委托类型的事件,其事件名称为:OnStateChange:
public delegate void StateChangeEventHandler();
public class YanlzProduct{
public StateChangeEventHandler OnStateChange;
}
++++【事件Event】:实现类似观察者设计模式,一对多的通知。(相当于C++的函数指针的一个列表。)
//立钻哥哥:Event事件在UI上的事件回调用途很常见:
public class YanlzEventManager : MonoBehaviour{
public delegate void MyClickAction();
public static event MyClickAction OnClicked;
void OnGUI(){
if(GUI.Button(new Rect(Screen.width/2-50, 5, 100, 30), “Click”)){
if(OnClicked != null){
OnClicked();
}
}
}
} //立钻哥哥:public class YanlzEventManager : MonoBehaviour{}
//立钻哥哥:收到点击事件随机改变颜色
public class YanlzTurnColorScript : MonoBehaviour{
void OnEnable(){
YanlzEventManager.OnClicked += MyTurnColor;
}
void OnDisable(){
YanlzEventManager.OnClicked -= MyTurnColor;
}
void MyTurnColor(){
Color col = new Color(Random.value, Random.value, Random.value);
renderer.material.color = col;
}
} //立钻哥哥:public class YanlzTurnColorScript : MonoBehaviour{}
++++事件和委托的区别:
--event后只能用“+=、-=”来添加或移除处理,使用“=”赋值会报错。(在一定程度上保证了event系统在一个事件触发后感兴趣的系统都会得到通知,而不会被一个错误的赋值把注册的处理都覆盖掉。)
--事件是一种特殊的委托的实例,或者说是受限制的委托,是委托的一种特殊应用,在类的外部只能施加+=、-=操作符,二者本质上是一个东西。
--事件只允许用add(+=)、remove(-=)方法来操作,这导致了它不允许在类的外部被直接触发,只能在类的内部适合的时机触发。(委托可以在外部被触发,但是别这么用。)(使用中,委托常用来表达回调,事件表达外发的接口。)
--事件不可以当作形参传递,但是委托可以。
--委托就是一种引用方法的类型,一旦为委托分配了方法,委托将与该方法具有完全相同的行为。
--委托方法的使用可以像其他任何方法一样,具有参数和返回值。
--委托可以看作是对函数的抽象,是函数的“类”,委托的实例将代表一个具体的函数。
--一个委托可以搭载多个方法,所有方法被依次唤起,更重要的是,它可以使委托对象搭载的方法不需要属于同一类。
--委托是一个类,它定义了方法的类型,使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用IF-ELSE(Switch)语句,同时使得程序具有更好的可扩展性。
--使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时,可以依次调用所有绑定的方法。
--Event事件封装了委托类型的变量,使得:在类的内部,不管声明它是public还是protected,它总是private的。
++++匿名函数:
//立钻哥哥:使用匿名方法可以不用把外部变量(比如类成员)用参数传给专门的方法(事件处理),可以直接使用这些变量。
static void YanlzHandleDemoEvent(object sender, EventArgs e){
Debug.Log(“立钻哥哥:Handled by YanlzHandleDemoEvent”);
}
//1、立钻哥哥:为这个方法创建一个委托实例
EventHandle handler;
handler = new EventHandler(YanlzHandleDemoEvent); //handler = YanlzHandleDemoEvent;
handler(null, EventArgs.Empty);
//2、立钻哥哥:匿名方法,直接写回调方法的实现
string str = “立钻哥哥:Handled anonymously”;
handle = delegate(object sender, EventArgs e){
Debug.Log(str); //外部变量
Debug.Log(“立钻哥哥:Handled by YanlzHandleDemoEvent”);
};
handler(null, EventArgs.Empty);
++++Action:和delegate差不多的功能:
//立钻哥哥:模拟网络模块的类,收到消息后走回调。
public class YanlzNetworkManager{
Queue<Action<string>> Callbacks;
public YanlzNetworkManager(){
Callbacks = new Queue<Action<string>>();
}
public void SendMessage(Action<string> callback){
Callbacks.Enqueue(callbak);
}
public void Run(){
string getData = “立钻哥哥:这是从网络得到的消息”;
Action<string> callback = Callbacks.Dequeue();
Callback(getData);
}
} //立钻哥哥:public class YanlzNetworkManager{}
class YanlzProgram{
static void Main(string[] args){
YanlzNetworkManager networkMgr = new YanlzNetworkManager();
networkMgr.SendMessage((string data)=>{
MyCallback(data);
});
networkMgr.Run();
}
static void MyCallback(string data){
Debug.Log(“立钻哥哥:data=” + data);
}
} //立钻哥哥:class YanlzProgram{}
++框架知识点002:delegate委托
++++delegate关键字在编译器生成代码时会映射到调用Delegate和MulticastDelegate类的成员的方法调用。(可以使用定义方法签名的语法来定义委托类型,只需在添加delegate关键字即可。)
++++Delegate类:表示委托,委托是一种数据结构,它引用静态方法或引用类实例及该类的实例方法。(public abstract class Delegate : ICloneable, ISerializable{})
++++委托语法:关键字delegate + 返回值 + 委托名 + 参数。
++++public delegate int LovezuanzuanHandler<in T>(T left, T right);
++++delegate(委托)是表示将方法作为参数传递给其他方法。(委托类似于函数指针,但与函数指针不同的是,委托是面向对象的,类型安全的和保险的。)
++++委托(delegate)可以看成是一种数据类型,它可以定义变量。(不过是一种特殊的变量:委托定义的变量,可以接受的数值是一个或多个函数方法,可以理解成它是存放函数方法的变量,或理解成委托就是一个函数方法指针。)(将委托和函数方法关联起来,除了在创建对象的时候关联方法也可以通过“+=”绑定方法,也可以通过“-=”解绑来实现函数方法的关联。)
++++委托既能引用静态方法,也能引用实例方法。(基于委托开发事件驱动程序变得简单)(使用委托可以大大简化多线程编程的难度。)
++++委托是一个类,它定义了方法的类型,使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用IF-ELSE(Switch)语句,同时使得程序具有更好的可扩展性。(使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时,可以依次调用所有绑定的方法。)(委托在编译的时候确实会编译成类,delegate是一个类,所以在任何可以声明类的地方都可以声明委托。)
++++C#使用委托将方法作为参数给另一个方法,委托将方法作为对象封装起来,允许在运行时间接地绑定一个方法调用。(在C和C++中利用函数指针)
++++C#中内置了三种委托方式:Action委托、Func委托、Predicate委托等。
++立钻哥哥带您理解:C#委托
++++立钻哥哥:委托是C#编程一个非常重要的概念,也是一个难点。
++++委托的理解:
--从数据结构来讲,委托和类一样是一种用户自定义类型。
--从设计模式来讲,委托(类)提供了方法(对象)的抽象。
++++委托是方法的抽象,它存储的就是一系列具有相同签名和返回类型的方法的地址。(调用委托的时候,委托包含的所有方法将被执行。)
++++委托是类型,与类一样,委托变量必须在被用来创建变量以及类型对象之前声明:
--delegate void YanlzDelegate(int x); //立钻哥哥:delegate是委托的关键字
--YanlzDelegate del1, del2, del3; //声明委托变量
--del1 = new YanlzDelegate(myClass1.MyFunc1); //del1 = myClass1.MyFunc1;
--del2 = new YanlzDelegate(myClass2.MyFunc2); //del2 = myClass2.MyFunc2;
--del3 = del1 + del2; //立钻哥哥:组合调用列表
--del3(); //委托调用(调用空委托会抛异常)
++++委托中匿名方法的使用:delegate(参数){ 语句块 }
--delegate int MyYanlzDelegate(int x); //立钻哥哥:定义一个委托
--MyYanlzDelegate del = delegate(int x){ return x; } //匿名方法不会显式声明返回值
++++Lambda表达式:主要用来简化匿名方法的语法。(编译器已知道将方法赋值给委托,就可以删除delegate关键字了)
--Lambda运算符:“=>”:读作“goes to”
--delegate int YanlzDelegate(int x); //立钻哥哥:定义一个委托
--YanlzDelegate del1 = delegate(int x){ return x; } //匿名方法
--YanlzDelegate del2 = (int x)=>{ return x; } //Lambda表达式
--YanlzDelegate del3 = x => { return x; } //简写的Lambda表达式
++示例:C#委托应用举例
//立钻哥哥:通过一个简单的示例,加深理解delegate委托
using System;
namespace YanlzUsingDelegate{
class MyStudent{
private string name; //立钻哥哥:姓名
private double score; //成绩
//立钻哥哥:构造函数,初始化学生姓名和成绩
public MyStudent(string name, double score){
this.name = name;
this.score = score;
}
//立钻哥哥:求最大值(静态方法)
public static object YanlzFuncMax(object obj1, object obj2){
MyStudent st1 = (MyStudent)obj1;
MyStudent st2 = (MyStudent)obj2;
return st1.score > st2.score ? st1 : st2;
}
//立钻哥哥:求最小值(静态方法)
public static object YanlzFuncMin(object obj1, object obj2){‘
MyStudent st1 = (MyStudent)obj1;
MyStudent st2 = (MyStudent)obj2;
return st1.score < st2.score ? st1 : st2;
}
} //立钻哥哥:class MyStudent{}
class YanlzProgram{
delegate object YanlzDelegate(object o1, object o2);
//立钻哥哥:以委托作为参数定义方法,求最大值和最小值
static MyStudent YanlzFunc(MyStudent st1, MyStudent st2, YanlzDelegate myFunc){
return (MyStudent)myFunc(st1, st2);
}
static void Main(string[] args){
MyStudent[] stus = {
new MyStudent(“Yanlz”, 80),
new MyStudent(“zuanzuan”, 90),
new MyStudent(“wangjue”, 100),
new MyStudent(“xiaojue”, 95)
}; //立钻哥哥:创建学生数组
//立钻哥哥:创建委托对象,关联静态方法
YanlzDelegate delegateMax = new YanlzDelegate(MyStudent.YanlzFuncMax);
YanlzDelegate delegateMin = new YanlzDelegate(MyStudent.YanlzFuncMin);
MyStudent maxStu, minStu;
maxStu = minStu = stus[0];
//立钻哥哥:利用YanlzFunc()方法求最大值和最小值
for(int i = 1; i < stus.Length - 1; i++){
maxStu = YanlzFunc(maxStu, stus[i], delegateMax);
minStu = YanlzFunc(minStu, stus[i], delegateMin);
}
Debug.Log(“立钻哥哥:最大值{0},最小值{1}”, maxStu, minStu);
}
} //立钻哥哥:class YanlzProgram{}
} //立钻哥哥:namespace YanlzUsingDelegate{}
++++立钻哥哥:该程序中,方法的回调体现在YanlzFucn()方法中,它包含一个YanlzDelegate类型的参数myFunc,通过该参数,可以将MyStudent.YanlzFuncMax()方法传递到YanlzFunc()方法中求最大值,将MyStudent.YanlzFuncMin()方法传递到YanlzFunc()方法中秋最小值。
++立钻哥哥带您拓展delegate委托
++++public delegate void GreetingDelegate(string name); //立钻哥哥:声明委托
++++public void GreetingPeople(string name, GreetingDelegate method){} //委托作参数
++++实际上,委托在编译的时候确实会编译成类,delegate是一个类,所以在任何可以声明类的地方都可以声明委托。
++++委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用IF-Else(Switch)语句,同时使得程序具有更好的可扩展性。
++++利用委托实现一个简单功能:
//立钻哥哥:method的类型就是委托,method参数能够确定方法的种类,method代表方法的参数类型和返回类型。
class YanlzHelloWorld{
public delegate void YanlzGreetingDelegate(string name);
public static void EnglishGreeting(string name){
Debug.Log(“立钻哥哥:hello, ” + name);
}
public static void ChineseGreeting(string name){
Debug.Log(“立钻哥哥:你好, ” + name);
}
public void YanlzGreetingPeople(string name, YanlzGreetingDelegate myMethod){
myMethod(name);
}
}
//1、立钻哥哥:简单测试
class YanlzProgram01{
static void Main(string[] args){
YanlzHelloWorld myHelllo = new YanlzHelloWorld();
myHello.YanlzGreetingPeople(“立钻哥哥”, YanlzHelloWorld.ChineseGreeting);
}
}
//2、立钻哥哥:声明委托变量
class YanlzProgram02{
static void Main(string[] args){
YanlzHelloWorld myHello = new YanlzHelloWorld();
YanlzHelloWorld.YanlzDelegate delegate1, delegate2;
delegate1 = YanlzHelloWorld.EnglishGreeting;
delegate2 = YanlzHelloWorld.ChineseGreeting;
myHello.YanlzGreetingPeople(“yanlz”, delegate1);
myHello.YanlzGreetingPeople(“立钻哥哥”, delegate2);
}
}
//3、立钻哥哥:委托可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法:
YanlzHelloWorld.YanlzGreetingDelegate myDelegate;
myDelegate = YanlzHelloWorld.EnglishGreeting;
myDelegate += YanlzHelloWorld.ChineseGreeting;
YanlzHelloWorld myHello = new YanlzHelloWorld();
myHello.YanlzGreetingPeople(“立钻你哥哥”, myDelegate);
//4、立钻哥哥:尝试通过委托直接调用EnglishGreeting和ChineseGreeting
YanlzHelloWorld.YanlzGreetingDelegate myDelegate;
myDelegate = YanlzHelloWorld.EnglishGreeting;
myDelegate(“立钻哥哥”);
//5、立钻哥哥:多播委托,第一次用的是“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。(如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误)(可以使用“-=”取消对方法的绑定。)
YanlzHelloWorld.YanlzGreetingDelegate myDelegate = new YanlzHelloWorld.YanlzGreetingDelegate(YanlzHelloWorld.ChineseGreeting);
myDelegate += YanlzHelloWorld.EnglishGreeting;
myDelegate(“立钻哥哥”);
myDelegate -= YanlzHelloWorld.ChineseGreeting;
myDelegate(“立钻哥哥”);
++++匿名函数:
//立钻哥哥:利用委托实现一个按钮的点击事件
public delegate void YanlzClickHandler();
//1、立钻哥哥:普通的委托调用(赋值对应的方法或直接new关联一个方法)
class MyButton{
public static void MyClickFinished(){
Debug.Log(“立钻哥哥:按钮被点击了!”);
}
}
YanlzClickHandler myDelegate;
myDelegate = MyButton.MyClickFinished;
myDelegate();
//2、立钻哥哥:利用匿名函数(在初始化时内敛声明的方法,使得委托的语法更简洁)
YanlzClickHandler myClick = delegate(){
Debug.Log(“立钻哥哥:匿名函数:按钮被点击了”);
}
myClick();
++++C#中内置了三种委托形式:Func委托、Action委托、Predicate委托。
--Func委托的类型(有返回值的函数:TResult:返回类型):
----delegate TResult Func<TResult>();
----delegate TResult Func<T1, TResult>(T1 arg1);
----delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
----delegate TResult Func<T1, T2, T3, Tn, TResult>(T1 arg1, T2 arg2, T3 arg3, Tn argn);
----示例:使用Func委托函数带有返回值,即TResult:
//1、立钻哥哥:没有参数(delegate TResult Func
Func<string> myFunc01 = delegate(){
return “立钻哥哥:我是Func
};
string myResultStr01 = myFunc01();
Debug.Log(“立钻哥哥:result: ” + myResultStr01);
//2、立钻哥哥:有1个参数(delegate TResult Func
Func<string, string> myFunc02 = delegate(string s){
return s.ToLower();
};
string myResultStr02 = myFunc02(“YANLIZUAN”);
Debug.Log(“立钻你哥哥:result:” + myResultStr02);
//3、立钻哥哥:有2个参数(delegate TResult Func
Func<string, string, string> myFunc03 = delegate(string str1, string str2){
return str1 + “ ” + str2;
};
Debug.Log(“立钻哥哥:result:” + myFunc03(“立钻哥哥”, “Func
--Action委托:
----delegate void Action();
----delegate void Action<T>(T arg);
----delegate void Action<T1, T2>(T1 arg1, T2 arg2);
----delegate void Action<T1, T2, T3, Tn>(T1 arg1, T2 arg2, T3 arg3, Tn argn);
--Func委托和Action委托的唯一区别:在于代理的方法(函数)有么有返回值。
----有返回值选择Func委托。(delegate TResult Func<TResult>())
----没有返回值选择Action委托。(delegate void Action())
--系统内置的Func委托和Action委托绝大多数情况下可以适配任何情况,无需我们再写大量的代码去定义委托。(根据特殊情况还需我们手动定义委托)
++++Lambda表达式:
--(参数)=>{语句块}
--“Lambda”表达式是一个匿名函数,是一种高级的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。(它可以包含表达式和语句,并且可以用创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内敛表达式。)(Lambda表达式都使用Lambda运算符“=>”,读作“goes to”)
--Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块。
++框架知识点003:Event事件
++++event事件是基于委托(event是在multicast delegate的基础上演变来的)。事件是一种特殊的委托的实例,或者说是受限制的委托,是委托一种特殊应用,在类的外部只能施加+=、-=操作符,事件和委托本质上是一个东西。
++++event事件只允许用add(+=)、remove(-=)方法来操作,这导致了它不允许在类的外部被直接触发,只能在类的外部适合的时机触发。(委托可以在外部被触发,但是别这么用。)(委托常用来表达回调,事件表达外发的接口。)
++++event事件不可以当作形参传递,delegate委托可以。
++++自定义事件的一般步骤:
--步骤1、声明关于事件的delegate委托;(public delegate void YanlzChangeHandler();)
--步骤2、声明event事件;(public event YanlzChangeHandler OnYanlzChangeEvent;)
--步骤3、编写触发事件的函数;(public void DoChange(){ OnYanlzChangeEvent(); })
--步骤4、创建事件处理程序;(void MyHandlerAlarm(){})
--步骤5、注册事件处理程序;(OnYanlzChangeEvent += MyHandlerAlarm;)
--步骤6、在适当的条件下触发事件;(DoChange();)
++立钻哥哥:通过一个简单例子熟悉event事件
using System;
namespace YanlzPublisherEvent{
//出版社
class MyPublisher{
public delegate void PublishHandler(); //定义一个委托类型
public event PublishHandler OnPublishEvent; //声明一个事件
//事件触发的方法
public void DoMyIssue(){
if(null != OnPublishEvent){
Debug.Log(“立钻哥哥:有新刊物更新出版了”);
OnPublishEvent(); //事件触发
}
}
} //立钻哥哥:class MyPublisher{}
//订阅者
class MySubscriber{
//在事件订阅者中定义事件处理程序
public void Recevie(){
Debug.Log(“立钻哥哥:收到信出版的刊物了”);
}
} //立钻哥哥:class MySubscriber{}
class MyStory{
static void Main(){
MyPublisher myPub = new MyPublisher();
MySubscriber mySub = new MySubscriber();
//向事件发行者订阅一个事件
myPub.OnPublishEvent += new MyPublisher.PublishHandler(mySub.Receive);
myPub.DoMyIssue(); //触发事件
}
} //立钻哥哥:class MyStory{}
} //立钻哥哥:namespace YanlzPublisherEvent{}
++event事件简单示例:熟悉event事件
//立钻哥哥:通过模拟简单的服务器和客户端订阅和发布
//服务器
public class MyServer{
public event Action<string> MyMsgEvent; //服务器发布的事件
public void DoMySend(string msg){
if(null != MyMsgEvent){
Debug.Log(“立钻哥哥:Server推送的消息:” + msg);
MyMsgEvent(msg);
}
}
} //立钻哥哥:public class MyServer
//客户端
public class MyClient{
public MyClient(MyServer myServ){
myServ.MyMsgEvent += Receive; //客户端订阅
}
public void Receive(string msg){
Debug.Log(“立钻哥哥:Client收到了通知:” + msg);
}
} //立钻哥哥:public class MyClient{}
//调用
public class YanlzProgram{
static void Main(){
MyServer myServ = new MyServer();
MyClient myClient = new MyClient(myServ);
myServ.DoMySend(“立钻哥哥:serv发送消息了”);
}
} //立钻哥哥:public class MyProgram{}
++event事件示例:通过一个猫和老鼠的经典案例熟悉event事件
//立钻哥哥:通过猫和老鼠的案例熟悉event事件
using System;
namesapce YanlzDelegateEvent{
//定义一个猫类
class MyCat{
private string name; //猫的名字
//构造函数
public MyCat(string name){
this.name = name;
}
public delegate void CatShoutDelegate(); //定义一个委托
public event CatShoutDelegate CatShoutEvent; //定义一个事件
//定义一个猫叫的方法
public void DoMyCatShout(){
Debug.Log(“立钻哥哥:喵喵~,这只猫是{0}”, name);
//执行猫叫方法的时候,先判断委托的实例对象是否存在
if(null != CatShoutEvent){
CatShoutEvent(); //执行事件的委托
}
}
} //立钻哥哥:class MyCat{}
class MyMouse{
private string name;
public MyMouse(string name){
this.name = name;
}
public void MyMouseRun(){
Debug.Log(“立钻哥哥:老猫来了,快跑呀! 我是{0}”, this.name);
}
} //立钻哥哥:class MyMouse{}
class MyMainClass{
public static void Main(string[] args){
MyCat myCat = new MyCat(“Tom”);
MyMouse mouse1 = new MyMouse(“Jerry”);
MyMouse mouse2 = new MyMouse(“Jack”);
//将Mouse的Run方法通过示例委托给CatShoutDelegate登记到猫的事件中
myCat.CatShoutEvent += new Cat.CatShoutDelegate(mouse1.MyMouseRun);
myCat.CatShoutEvent += new Cat.CatShoutDelegate(mouse2.MyMouseRun);
myCat.DoMyCatShout(); //立钻哥哥:猫来了
}
} //立钻哥哥:class MyMainClass{}
} //立钻哥哥:namespace YanlzDelegateEvent{}
++立钻哥哥带您进入event事件
++++event事件机制的两个主体是:发布者(publisher)和订阅者(subscriber)。
--发布者(publisher):发布某个事件的类或结构。
--订阅者(subscriber):注册在事件发生时得到通知的类或结构。
--事件处理程序(event handler):订阅者收到通知时要执行的方法。
--触发(raise)事件:就是发布通知(依次执行委托列表的方法)。
++++示例强化:实现点击一个按钮后,画布上出现一张图片。
--画布类(订阅者)有一个显示图片的方法(事件处理程序),把这个方法添加到按钮(发布者)的事件的委托中,当按钮被点击(触发事件),就执行事件里面的委托,这委托里面就会执行显示图片的方法。
//立钻哥哥:实现点击一个按钮后,画布上出现一张图片
namespace YanlzEventDemo{
//发布者(publisher)
class MyButton{
public event EventHandler ButtonClickedEvent; //EventHander系统推荐使用
public void OnButtonClicked(){
ButtonClickedEvent(this, null); //立钻哥哥:触发事件
}
} //立钻哥哥:class MyButton{}
//订阅者
class MyCanvas{
private string myPicture = “立钻哥哥:I am a picture!”;
public MyCanvas(MyButton myBtn){
myBtn.ButtonClickedEvent += ShowPicture; //订阅事件
}
//事件处理程序(签名要和委托匹配)
void ShowPicture(object source, EventArgs e){
Debug.Log(“立钻哥哥:picture:” + myPicture);
}
} //立钻哥哥:class MyCanvas
class YanlzProgram{
static void Main(){
MyButton myButton = new MyButton();
MyCanvas myCanvas = new MyCanvas(myButton);
myButton.OnButtonClicked();
}
} //立钻哥哥:class YanlzProgram
} //立钻哥哥:namespace YanlzEventDemo{}
++event事件实战:立钻哥哥通过一个示例揭示event事件机理
++++事件:可看做是一个或若干个动作,比如射击事件,包含几个动作:1、子弹上膛(Load),2、拉枪栓(Pull),3、瞄准(Aim),4、扣扳机(Fire)等。
//立钻哥哥:通过这个射击示例,深入熟悉event事件
using System;
namespace YanlzEventDemo{
public delegate void ActHandler();
class GunFire{
public static void GunLoad(){
}
public static void GunPull(){
}
public static void GunAim(){
}
public static void GunFire(){
}
} //立钻哥哥:class GunFire{}
class MySoldier{
public event ActHandler MyFireEvent;
public void OnFire(){
MyFireEvent();
}
} //立钻哥哥:class MySoldier{}
class YanlzProgram{
public static void Main(string[] args){
MySoldier mySoldier = new MySoldier();
mySoldier.MyFireEvent += GunFire.GunLoad;
mySoldier.MyFireEvent += GunFire.GunPull;
mySoldier.MyFireEvent += GunFire.GunAim;
mySoldier.MyFireEvent += GunFire.GunFire;
bool canFireCmd = true; //立钻哥哥:模拟开枪指令
if(canFireCmd){
mySolider.OnFire();
}
}
} //立钻哥哥:class YanlzProgram{}
} //立钻哥哥:namespace YanlzEventDemo{}
++event事件实战:立钻哥哥利用一个demo来加深理解event事件
++++立钻哥哥:通过一个Demo来模拟服务器、客户端的消息推送接收处理。
//立钻哥哥:Demo模拟网络消息处理(Server.cs、Client.cs、Prorams.cs)
//立钻哥哥:模拟服务器(YanlzEventDemo/MyServer.cs)
using System;
namesapce YanlzEventDemo{
public delegate void MySendMsgHandler(string msg); //定义delegate
//模拟服务器:推送消息
public class MyServer{
public static event MySendMsgHandler mySendMsgEvent; //事件是委托的实例对象
//服务器端推送消息给客户端
public void DoSendMsg(string msg){
Debug.Log(“立钻哥哥:服务器开始推送消息了~~~~~”);
//不为空,表示客户端订阅了事件(mySendMsgEvent由客户端初始化)
if(null != mySendMsgEvent){
mySendMsgEvent(msg); //执行委托事件(执行它注册的方法)
}
}
} //立钻哥哥:public class MyServer{}
} //立钻哥哥:namespace YanlzEventDemo
//立钻哥哥:模拟客户端(YanlzEventDemo/MyClient.cs)
using System;
namespace YanlzEventDemo{
//模拟手机客户端:订阅消息推送事件
class MyClient{
//订阅事件:客户端订阅服务器推送消息的功能
public void MySubscription(){
Debug.Log(“立钻哥哥:客户端订阅了推送事件了-----”);
MyServer.mySendMsgEvent += Server_MySendMsgEvent; //给事件绑定方法
}
private void Server_MySendMsgEvent(string msg){
Debug.Log(“立钻哥哥:客户端接收到的推送消息:msg:” + msg);
}
} //立钻哥哥:class MyClient{}
} //立钻哥哥:namespace YanlzEventDemo{}
//立钻哥哥:模拟控制程序(YanlzEventDemo/MyProgram.cs)
namespace YanlzEventDemo{
//模拟控制程序
public class MyProgram{
static void Main(string[] args){
MyClient myClient = new MyClient();
MyServer myServer = new MyServer();
myClient.MySubscription(); //客户端订阅消息
myServer.DoSendMsg(“立钻哥哥:推送的消息来了~~~”); //服务器推送消息
}
} //立钻哥哥:public class MyProgram{}
} //立钻哥哥:namespace YanlzEventDemo{}
++event事件实战:立钻哥哥通过示例带您了解event事件
++++立钻哥哥:尝试用一个比较通俗的例子拓展event事件的应用场景
//立钻哥哥:模拟水壶烧水事件:(热水器、警报器、显示器)根据水温提示
using System;
namespace YanlzEventDemo{
public delegate void MyAlarmHandler(int temperature); //报警委托
public delegate void MyDisplayHandler(int temperature); //显示委托
//热水器类
class MyHeater{
private int temperature = 10; //温度
public event MyAlarmHandler OnMyAlarmEvent; //报警事件
public event MyDisplayHandler OnMyDisplayEvent; //显示事件
public void BoildWater(int minute){
Debug.Log(“立钻哥哥:现在水温{0}”, this.temperature);
this.temperature += minute * 10; //立钻哥哥:模拟水温升高
if(this.temperature >= 95){
OnMyAlarmEvent(this.temperature);
OnMyDisplayEvent(this.temperature);
}
}
} //立钻哥哥:class MyHeater{}
//报警器类
class MyAlarm{
public void MyMakeAlert(int temperature){
Debug.Log(“立钻哥哥:滴滴滴,水开了:温度{0}”, temperature);
}
} //立钻哥哥:class MyAlarm{}
//显示器类
class MyDisplay{
public void MyShowMsg(int temperature){
Debug.Log(“立钻哥哥:动画显示水开了,水温{0}”, temperature);
}
}
class MyProgram{
static void Main(string[] args){
MyHeater myHeater = new MyHeater();
MyAlarm myAlarm = new MyAlarm();
MyDisplay myDisplay = new MyDisplay();
//建立关联
myHeater.OnMyAlarmEvent += myAlarm.MyMakeAlert;
myHeater.OnMyDisplayEvent += myAlarm.MyShowMsg;
meHeater.BoilWater(20); //立钻哥哥:模拟烧水20分钟
}
} //立钻哥哥:class MyProgram{}
} //立钻哥哥:namespace YanlzEventDemo{}
++框架知识点004:EventHandle
++++EventHandle委托是C#预定义的一个事件委托。
namespace System{
[Serializable]
[ComVisible(true)]
public delegate void EventHandler(object sender, EventArgs e);
//object sender:事件源(System.Object)
//EventArgs e: 不包含事件数据的对象(System.EventArgs)
}
++++EventHandle泛型:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
//object sender:事件源(System.Object)
//TEventArgs e:包含事件数据的对象(TEventArgs)
++++EventHandler是一个预定义的委托,专用于表示不生成数据的事件的事件处理程序方法。(如果事件生成数据,则必须提供自己的自定义事件数据类型,并且必须要创建一个委托,其中第二个参数的类型为自定义类型,要么使用泛型EventHandler委托类并用自定义类型替代泛型类型参数。)
++++EventHandler事件委托:事件就是类或者对象的状态发生改变时,对象或类发出的信息或通知。(发出信息的对象或者类称为“事件源”,对事件处理的方法称为“接收者”)(通常事件源在发出状态改变信息,它并不知道由哪个事件接收者处理。)(这就需要通过一种机制来协调事件源和接收者,在C++中通过函数指针来完成的,在C#中事件使用委托来为触发时将调用的方法提供类型安全的封装。)
--1、声明一个委托:public delegate void EventHandler(object sender, EventArgs e);
--2、声明一个事件:public event EventHandle OnChangedEvent;
--3、引用一个事件:public DoChanged(EventArgs e){ OnChangeEvent(this, e); }
--4、定义事件处理函数:public YanlzTest_OnChanged(object sender, EventArgs e){}
--5、订阅事件:ylzClass.OnChangedEvent += new EventHandle(YanlzTest_OnChanged);
++EventHandle委托示例:
//立钻哥哥:EventHandle简单应用场景
using System;
namespace YanlzEventHandlerTest{
class MyMainProgram{
public delegate void EventHandler(string a); //委托
public static event EventHandler OnYanlzSetCodeEvent; //事件
static void Main(string[] args){
MyMainProgram.OnYanlzSetCodeEvent += DoMyGetCode; //注册
OnYanlzSetCodeEvent(“立钻哥哥:触发了”); //触发
}
public static void DoMyGetCode(string str){
Debug.Log(“立钻哥哥:获得触发消息:{0}”, str);
}
} //立钻哥哥:class MyMainProgram{}
} //立钻哥哥:namespace YanlzEventHandlerTest{}
++自定义EventHandle实现参考:了解EventHandle的机制
//立钻哥哥:自定义EventHandle示例
using System;
namespace YanlzEventHandleDemo{
public class YanlzMyText{
public string textStr = “”;
public delegate void YanlzChangedEventHandle(object sender, EventArgs e);
public event YanlzChangedEventHandle OnChangedEvent;
protected void DoChangedText(EventArgs e){
if(null != OnChangedEvent){
OnChangedEvent(this, e);
}
}
public string HelloText{
get{
return textStr;
}
set{
textStr = value;
this.DoChangedText(new EventArgs());
}
}
} //立钻哥哥:public class YanlzMyText{}
class MyMainProgram{
static void Main(string[] args){
YanlzMyText myText = new YanlzMyText();
myText.OnChangedEvent += new YanlzMyText.YanlzChangedEventHandle(MyMainTextChange);
//立钻哥哥:循环测试
string str = “”;
while(str != “quit”){
Console.WriteLine(“立钻哥哥:Please Enter a string:”);
str = Console.ReadLine();
myText.HelloText = str;
}
}
public static void MyMainTextChange(object sender, EventArgs e){
Debug.Log(“立钻哥哥:text has been changed : {0}”, ((YanlzMyText)sender).HelloText);
}
} //立钻哥哥:class MyMainProgram{}
} //立钻哥哥:namespace YanlzEventHandlerDemo{}
++EventHandle事件委托简单示例
//立钻哥哥:通过一个简单的EventHandle事件委托示例熟悉EventHandle机制。
using Sytem;
namespace YanlzEventHandleDemo{
//事件参数,必须继承类EventArgs
public class YanlzAddEventData : EventArgs{
public int a;
public int b;
} //立钻哥哥:public class YanlzAddEventData : EventArgs{}
public class MyEventHandleTest{
private event EventHandler<YanlzAddEventData> OnYanlzAddEvent; //事件对象
//初始化事件
public void InitYanlzAddEvent(EventHandler<YanlzAddEventData> myAddEvent){
this.OnYanlzAddEvent += new EventHandler<YanlzAddEventData>(myAddEvent);
}
//触发事件
public void DoCallAddEvent(){
if(null != OnYanlzAddEvent){
YanlzAddEventData myAddED = new YanlzAddEventData();
myAddED.a = 1;
myAddED.b = 2;
OnYanlzAddEvent(this, myAddED);
}
}
} //立钻哥哥:public class MyEventHandleTest{}
class YanlzTestMainProgram{
public static void Main(string[] args){
MyEventHandleTest myTest = new MyEventHandlerTest();
myTest.InitYanlzAddEvent(MyMainAddEvent); //传递事件处理函数地址
myTest.DoCallAddEvent(); //触发事件
}
//加法事件
public static void MyMainAddEvent(object sender, EventArgs e){
YanlzAddEventData myData = (YanlzAddEventData)e;
int c = myData.a + myData.b;
Debug.Log(“立钻哥哥:触发事件AddEvent: a + b = {0}”, c);
}
} //立钻哥哥:class YanlzTestMainProgram{}
} //立钻哥哥:namespace YanlzEventHandleDemo{}
++使用EventHandler传递参数
++++立钻哥哥:使用自定义控件时,需要对一个控件的click,mouseDown,mouseUp等事件的处理进行重新定义,以满足实际工程应用和要求:
--button1.Click -= new EventHandler(ButtonClick_Handler);
--button1.MouseUp -= new MouseEventHandler(ButtonClick_Handler);
--button1.Click += new EventHandler(ButtonClick_Handler);
--button1.MouseUp += new MouseEventHandler(ButtonUp_Handler);
++++.Net Framework中的事件模型基于事件委托,该委托将事件处理程序连接。
++++引发事件的两个元素:
--1、标识对事件提供响应的方法和委托。
--2、保存事件数据的类:
--public delegate void EventHandler(Object sender, EventArgs e);
--public event EventHandler NoDataEventHandler;
++框架知识点005:Func
++++Func
++++namespace{ public delegate TResult Func<TResult>(); }
++++Func的类型(使用Func委托函数必须带有返回值:TResult返回类型):
--delegate TResult Func<TResult>();
--delegate TResult Func<T, TResult>(T arg);
--delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
--delegate TResult Func<T1, T2, T3, Tn>(T1, arg1, T2 arg2, T3 arg3, Tn argn);
++++Func委托和Action委托的唯一区别就是代理的方法(函数)有没有返回值:有返回值选择Func委托,没有返回值选择Action委托。
++Func委托简单示例:
//立钻哥哥:简单示例Func委托
//1、delegate TResult Func
Func<string> myFunc01 = delegate(){
return “立钻哥哥:这是Func
};
string result01 = myFunc01();
Debug.Log(“立钻哥哥:输出结果result:” + result01);
//2、delegate TResult Func
Func<string, string> myFunc02 = delegate(string s){
return s.ToLower();
};
string result02 = myFunc02(“LOVEZUANZUAN”);
Debug.Log(“立钻哥哥:输出结果result:” + result02);
//3、delegate TResult Func
Func<string, string, string> myFunc03 = delegate(string str1, string str2){
return str1 + “ ” + str2;
};
Debug.Log(“立钻哥哥:输出结果result” + myFunc03(“立钻哥哥”, “Func
++Func
++++立钻哥哥尝试利用四种方式来剖析引入Func
//1、立钻哥哥:delegate显式定义
using System;
delegate bool YanlzWriteMethodHandler(); //立钻哥哥:delegate显式定义
public class YanlzMainTestDelegate{
public class MyOutputTarget{
public bool SendToFile(){
try{
string myFileName = Path.GetTempFileName();
StreamWirte myStreamWriter = new StreamWriter(myFileName);
myStreamWriter.WriteLine(“立钻哥哥:Hello World!”);
myStreamWriter.Close();
return true;
}catch{
return false;
}
}
}
public static void Main(){
MyOutputTarget myOutput = new MyOutputTarget();
YanlzWriteMethodHandler myMethodCall = myOutput.SendToFile;
if(myMethodCall()){
Debug.Log(“立钻哥哥:Success!”);
}else{
Debug.Log(“立钻哥哥:File write operation failed.”);
}
}
} //立钻哥哥:public class YanlzMainTestDelegate{}
//2、立钻哥哥:使用Func
using System;
//delegate bool YanlzWriteMethodHandler(); //立钻哥哥:delegate显式定义
public class YanlzMainTestDelegate{
public static void Main(){
MyOutputTarget myOutput = new MyOutputTarget();
//YanlzWriteMethodHandler myMethodCall = myOutput.SendToFile; //显式定义
Func<bool> myMethodCall = myOutput.SendToFile; //使用Func
if(myMethodCall()){
Debug.Log(“立钻哥哥:Success!”);
}else{
Debug.Log(“立钻哥哥:File write operation failed.”);
}
}
} //立钻哥哥:public class YanlzMainTestDelegate{}
//3、立钻哥哥:使用Func
using System;
//delegate bool YanlzWriteMethodHandler(); //立钻哥哥:delegate显式定义
public class YanlzMainTestDelegate{
public static void Main(){
MyOutputTarget myOutput = new MyOutputTarget();
//YanlzWriteMethodHandler myMethodCall = myOutput.SendToFile; //显式定义
//Func<bool> myMethodCall = myOutput.SendToFile; //使用Func
Func<bool> myMethodCall = delegate( return myOutput.SendToFile); //匿名
if(myMethodCall()){
Debug.Log(“立钻哥哥:Success!”);
}else{
Debug.Log(“立钻哥哥:File write operation failed.”);
}
}
} //立钻哥哥:public class YanlzMainTestDelegate{}
//4、立钻哥哥:使用Func
using System;
//delegate bool YanlzWriteMethodHandler(); //立钻哥哥:delegate显式定义
public class YanlzMainTestDelegate{
public static void Main(){
MyOutputTarget myOutput = new MyOutputTarget();
//YanlzWriteMethodHandler myMethodCall = myOutput.SendToFile; //显式定义
//Func<bool> myMethodCall = myOutput.SendToFile; //使用Func
//Func<bool> myMethodCall = delegate( return myOutput.SendToFile); //匿名
Func<bool> myMethodCall = ()=> myOutput.SendToFile; //Lambda表达式
if(myMethodCall()){
Debug.Log(“立钻哥哥:Success!”);
}else{
Debug.Log(“立钻哥哥:File write operation failed.”);
}
}
} //立钻哥哥:public class YanlzMainTestDelegate{}
++框架知识点006:Lambda表达式
++++“Lambda”表达式是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。它可以包含表达式和语句,并且可以用创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内敛表达式。(Lambda表达式使用运算符“=>”,读作“goes to”)
++++Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块。
++++函数MyFunc(string a, string b){}用Lambda表达式:(a, b)=>{}
++++函数bool MyMax(int a, int b){ return a > b ? a : b; }
--用Lambda表达式:(int a, int b)=>{ return a > b ? a : b; }
++++delegate(x,y){ return x*y; },用Lambda表达式:(x,y)=>x*y;
++++delegate(int x){ return x*x; },用Lambda表达式:(int x)=>{ return x*x; };
++++Lambda表达式是一种可用于创建委托或表达式目录树类型的匿名函数。(通过使用Lambda表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数。)(若要创建Lambda表达式,需要在Lambda运算符=>左侧指定输入参数,然后在另一侧输入表达式或语句块。)
++Lambda输入参数(()、arg、(arg1, arg2))
++++1、无参数使用(): ()=>DoYanlzMethod();
++++2、一个参数直接写出参数名: arg=>arg*arg;
++++3、多个参数使用,分割:(arg1, arg2)=>arg1==arg2;
++++4、参数类型无法推断时可以显式指定:(string arg1, char arg2)=>arg1.Split(arg2);
++++拓展:
(arg1, arg2)=>{
if(arg1 == arg2){
return 0;
}
return arg1 > arg2 ? 1 : -1;
}
++初识Lambda表达式:
//立钻哥哥:引入Lambda
class YanlzLambda{
public delegate void MyDelegateHandle00(); //不带参数的委托
public delegate void MyDelegateHandle01(string name); //带参数的委托
public delegate int myDelegateHandle02(int x, int y); //有参数有返回值的委托
}
MyDelegate01 myDelegate01 = (x)=>{
Debug.Log(“立钻哥哥:这是一个用Lambda表达式的委托,参数为:” + x);
};
myDelegate01(“立钻哥哥”); //调用
MyDelegate03 myDelegate03 = (x, y)=>{
Debug.Log(“立钻哥哥:这是一个用Lambda表达式委托带两个参数,和返回值”);
return x + y;
};
Debug.Log(“立钻哥哥:输出结果:” + myDelegate03(20, 30));
++Lambda表达式(C#编程)
++++立钻哥哥:Lambda表达式是一种可用于创建委托或表达式目录树类型的匿名函数。(通过使用Lambda表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数。)(若要创建Lambda表达式,需要在Lambda运算符=>左侧指定输入参数,然后在另一侧输入表达式或语句块。)
//立钻哥哥:创建Lambda表达式
delegate int MyDelegateHandle(int i);
static void Main(string[] args){
MyDelegateHandle myDelegate = x=> x * x;
int j = myDelegate(5); //立钻哥哥:j = 25
}
++++Lambda表达式中的变量范围:在定义lambda函数的方法内或包含Lambda表达式的类型内,Lambda可以引用范围内的外部变量。(以这种方式捕获的变量将进行存储以备在lambda表达式中使用,即使在其他情况下,这些变量将超出范围并进行垃圾回收。)(必须明确地分配外部变量,然后才能在lambda表达式中使用该变量)
//立钻哥哥:Lambda表达式规则演示
delegate bool MyDelegateHandle01();
delegate bool MyDelegateHandle02(int i);
class YanlMainTest{
MyDelegateHandle01 myDelegate01;
MyDelegateHandle02 myDelegate02;
public void MyTestMethod(int input){
int j = 0;
myDelegate01 = ()=>{ j = 10; return j > input; }
myDelegate02 = (x)=>{ return x == j; }
Debug.Log(“立钻哥哥:j = {0}”, j); //立钻哥哥:j=0;(delegate未调用)
bool boolResult = myDelegate01(); //立钻哥哥:调用delegate
Debug.Log(“立钻哥哥:j={0}, b={1}”, j, boolResult); //立钻哥哥:j=10, b=true;
}
static void Main(){
YanlzMainTest myTest = new YanlzMainTest();
myTest.MyTestMethod(5);
bool result = myTest.myDelegate02(10);
Debug.Log(“立钻哥哥:result:” + result); //立钻哥哥:输出:true
}
}
++++适用于Lambda表达式中的变量范围:
--捕获的变量将不会被作为垃圾回收,直至引用变量的委托符合垃圾回收的条件。
--在外部方法中看不到lambda表达式内引入的变量。
--Lambda表达式无法从封闭方法中直接捕获in、ref、out参数。
--Lambda表达式中的返回语句不会导致封闭方法返回。
--如果跳转语句的目标在块外部,则lambda表达式不能包含位于lambda函数内部的goto语句、break语句、continue语句等。(同样,如果目标在块内部,则在lambda函数块外部使用跳转语句也是错误的。)
++lambda应用C#排序
//立钻哥哥:通过一个C#排序熟悉lambda表达式
using System;
namespace YanlzLambdaLearn{
public class MyMainProgram{
public static List<KeyValuePair<int, string>> list_type;
static Dictionary<int, string> type_value = new Dictionary<int, string>();
public static void Main(string[] args){
type_value = addKey(type_value);
list_type = new List<KeyValuePair<int, string>>(type_value);
list_type.Sort((sort1, sort2)=>{
if(sort1.Key > sort2.Key){
return 1;
}else if(sort1.Key == sort2.Key){
return 0;
}else{
return -1;
}
});
}
public static Dictionary<int, string> addKey(Dictionary<int, string> dic){
dic.Add(5, “int”);
dic.Add(4, “float”);
dic.Add(6, “double”);
dic.Add(1, “short”);
dic.Add(7, “long”);
return dic;
}
} //立钻哥哥:public class MyMainProgram{}
} //立钻哥哥:namespace YanlzLambdaLearn{}
++框架知识点007:Type
++++Type类:https://msdn.microsoft.com/zh-cn/library/system.type(v=vs.110).aspx
++++Type类:表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
using System;
namespace System{
[ClassInterface(ClassInterfaceType.None), ComDefaultInterface(typof(_Type)), ComVisible(true)]
[Serializable]
public abstract class Type : MemberInfo, _Type, IReflect{
//Static Fields
//Static Properties
//Properties
//Constructors
//static Methods
//Methods
} //立钻哥哥:public abstract class Type : MemberInfo, _Type, IReflect{}
} //立钻哥哥:namespace System{}
++++C#中通过Type类可以访问任意数据类型信息。
++++【获取给定类型的Type引用】:
--1、使用typeof运算符,如:Type t = typeof(int);
--2、使用GetType()方法,如:int i; Type t = i.GetType();
--3、使用Type类静态方法GetType(),如:Type t = Type.GetType(“System.Double”);
++++【Type的属性】:
--1、Name:数据类型名;
--2、FullName:数据类型的完全限定名,包括命名空间;
--3、Namespace:数据类型的命名空间;
--4、BaseType:基类基本类型;
--5、UnderlyingSystemType:映射类型;
++++【Type的方法】:
--GetMethod():返回一个方法的信息;
--GetMethods():返回所有方法的信息;
++++Type类的重要方法:
//立钻哥哥:列举几个比较重要的Type类信息
using System;
using System.Reflection;
namespace System{
public abstract class Type : MemberInfo, _Type, IReflect{
public abstract Type BaseType{ get; }
public abstract string FullName{ get; }
public bool IsClass{ get; }
public bool IsPublic{ get; }
public abstract string NameSpace{ get; }
public static Type GetType(string typeName, bool throwOnError, bool ignoreCase);
public static Type GetType(string typeName, bool throwOnError);
public static Type GetType(string typeName);
public override bool Equals(object o);
public bool Equals(Type o);
public MemberInfo[] GetMember(string name);
public MemberInfo[] GetMembers();
public MethodInfo[] GetMethods();
public override string ToString();
}
}
++Type类示例参考
++++Retrieving a Type object:
//立钻哥哥:检索Type类型
using System;
public class YanlzMainExample{
public static void Main(){
object[] values = { “立钻哥哥”, true, 2008, 199.99, ‘w’ };
foreach(var value in values){
Console.WriteLine(“立钻哥哥:{0}-type{1}”, value, value.GetType().Name);
}
}
//”立钻哥哥”n- type String
//true - type Boolean
//2008 - type Int32
//199.99 - type Double
//w - type Char
}
++++Comparing type objects for equality:
//立钻哥哥:比较Type类型
using System;
public class YanlzTypeMainExample{
public static void Main(){
long num1 = 1635499;
int num2 = 16208;
double num3 = 1639.99;
long num4 = 193688779;
Type t = num1.GetType(); //立钻哥哥:获得Type类型
//立钻哥哥:类型比较
Console.WriteLine(“equal:{0}”, Object.ReferenceEquals(t, num2.GetType())); //False
Console.WriteLine(“equal:{0}”, Object.ReferenceEquals(t, num3.GetType())); //False
Console.WriteLine(“equal:{0}”, Object.ReferenceEquals(t, num4.GetType())); //True
}
}
++C#中typeof与GetType()的区别
++++立钻哥哥:C#中任何对象都具有GetType()方法,它的作用和typeof相同,返回Type类型的当前对象的类型。(都是为了获取某个实例具体引用的数据类型System.Type)
++++typeof和GetType的区别:
--1、typeof是运算符,GetType是方法;
--2、GetType()是基类System.Object的方法(只有建立一个实例之后才能被调用);
--3、typeof的参数只能是int、string、自定义类型,不能是实例;
--4、GetType()和typeof都返回System.Type的引用;
--5、typeof:得到一个class的Type;
--6、GetType():得到一个class的实例的Type;
++++GetType()方法是基类System.Object的一个方法:
//立钻哥哥:我们来看看Object基类
using System;
namespace System{
public class Object{
//Constructors
public Object();
//Static Methods
public static bool Equals(object objA, object objB);
internal static extern bool InternalEquals(object objA, object objB);
internal static extern int InternalGetHashCode(object obj);
public static bool ReferenceEquals(object objA, object objB);
//Methods
public virtual bool Equals(object obj);
private void FieldGetter(string typeName, string fieldName, ref object val);
private void FieldSetter(string typeName, string fieldName, object val);
protected override void Finalize();
private FieldInfo GetFieldInfo(string typeName, string fieldName);
public FieldInfo GetFieldInfo(string typeName, string fieldName);
public virtual int GetHashCode();
public extern Type GetType(); //立钻哥哥:fixhere
protected extern object MemberwiseClone();
public virtual string ToString();
} //立钻哥哥:public class Object{}
} //立钻哥哥:namespace System{}
++++【System.Type类】:定义了很多成员,可以用来检查某个类型的元数据,它们返回的类型大多位于System.Reflection命令空间中。(Type.GetMethods()返回一个MethodInfo类型的数组)(Type.GetFields返回一个FieldInfo类型的数组)
++++【使用System.Object.GetType()得到Type引用】:可以使用多种方法得到一个Type类的实例。但是,由于Type是一个抽象类,不能直接使用new关键字创建一个Type对象。(我们首选使用System.Object定义的GetType()方法,它返回一个表示当前对象元数据的Type类的实例。)
++++使用自定义类实例得到类型信息:
YanlzClass myClass = new YanlzClass(); //立钻哥哥:自定义的类
Type mytype = myClass.GetType();
MethodInfo[] methodInfo = myType.GetMethods();
MemberInfo[] memberInfo = myType.GetMembers();
++C#反射之Type类
++++立钻哥哥:反射的作用:查看和遍历类型和类型的元数据;动态创建类型实例,动态的调用所创建的实例方法和字段,属性,延迟绑定方法和属性。
++++反射的核心类是Type类:封装了关于类型的元数据,是进行反射的入口。(当获得了类型的Type对象后,可以根据Type提供的属性和方法获得这个类型的信息,包括字段,属性,事件,参数,构造函数等。)
++++Type t = Type.GetType(“System.IO.Stream”); //立钻哥哥输出:System.IO.Stream
++++Type t = typeof(System.IO.Stream); //立钻哥哥输出:System.IO.Stream
++++string name = “立钻哥哥”; Type t = name.GetType(); //立钻哥哥输出:System.String
++++YanlzClass myClass = new YanlzClass(); Type t = myClass.GetType(); //YanlzNS.YanlzClass
++立钻哥哥推荐的拓展学习链接(Link_Url):
++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/
++++框架知识点:https://blog.csdn.net/VRunSoftYanlz/article/details/80862879
++++游戏框架(UI框架夯实篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80781140
++++游戏框架(初探篇):https://blog.csdn.net/VRunSoftYanlz/article/details/80630325
++++设计模式简单整理: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知识点0001:https://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引擎基础: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
++++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 学习空间: http://blog.csdn.net/VRunSoftYanlz/
--_--VRunSoft : lovezuanzuan--_--