委托
概念
自定义的类型,与结构体、枚举、类都是自定义类型
委托的使用
1、定义委托类型
2、通过委托类型定义委托类型的变量
3、对委托类型的变量进行赋值:
- 方法赋值给委托变量时,方法后没有括号
- 方法后带有括号,表示调用方法
4、调用委托的变量
- 变量名(填入实际参数)
- 最好判断委托变量是否是空
//声明委托类型 public delegate void TestDelegate1(); public delegate bool TestDelegate2(int x); public delegate void TestStringDele(string str); static void Main(string[] args) { //声明委托类型对象 TestDelegate1 t1 = new TestDelegate1(Test1); //委托的调用 t1(); TestStringDele t2 = new TestStringDele(Test2); //t2("Test2参数"); t2.Invoke("Test2参数");//委托的执行方式 TestDelegate2 t3 = new TestDelegate2(Test3); bool b = t3(3); Console.WriteLine(b); Console.ReadKey(); } /// <summary> /// 此时静态是因为Main函数是静态的 /// </summary> public static void Test1(){ Console.WriteLine("Test1"); } public static void Test2(string str) { Console.WriteLine("Test2:"+str); } public static bool Test3(int x) { return x > 0 ? true : false; }
委托变量(作用1)
存储多个签名与委托类型相同的方法,只能存储于委托类型签名一致的方法
签名 = 返回值 + 参数列表
委托变量只能存储的方法
- 返回值类型必须与委托类型的返回值类型相同
- 参数列表必须与委托类型的参数列表相同(类型一致,个数一致,顺序一致)
方法参数是委托类型(作用2)
能将一个方法(方法的逻辑)传递到另一个方法中
class Program { public delegate void MoveDel(); public delegate int Move2(int num); static public Move2 mm; //定义Move2类型的变量mm static void Main(string[] args) { Test3(Test2); //调用Test3把符合Move2委托类型的的方法Test2赋值给mm Console.WriteLine(mm(10)); //参数传给mm 调用Test2方法 } static int Test2(int num) { return num; } static void Test3(Move2 move) { mm = move; //把符合委托Move2的方法赋值给mm } }
练习:
//定义一个Student类型, 本质是结构体 struct Student { } //1.定义委托类型, 必须指定返回值类型和参数列表 public delegate void TestDel();//TestDel 就是一个委托类型 static void Main(string[] args) { //通过Student类型可以定义Student类型的变量 Student s; //Student 是类型 s 是变量 int a;// int 是类型 a 是变量 //2. 定义委托的变量 TestDel del; //TestDel 是委托类型 del 是变量 是TestDel类型的变量 //3. 对委托变量赋值 del = new TestDel(Func1);//第一种直接赋值方式 //表示将Func1方法赋值给del, 但是并没有执行Func1的方法 del = Func1;//第二种直接赋值方式 //表示执行(调用)Func4方法,将Func4方法的返回值赋值给del del = Func4(); //4.委托变量的调用 if(del != null) { del(); } Console.ReadKey(); } static TestDel Func4() { return null; } static void Func1() { } static bool Func2() { return true; } static void Func3(int a) { }
练习2:排序
public struct Student { public string name; public int age; public int height; public int weight; public Student(string name, int age, int height,int weight) { this.name = name; this.age = age; this.height = height; this.weight = height; } public override string ToString() { return string.Format("{0},年龄{1},身高{2},体重{3}", name, age, height, weight); } } static void Main(string[] args) { List<Student> list = new List<Student>(); list.Add(new Student("吕布",23,190,180)); list.Add(new Student("貂蝉",18,165,80)); list.Add(new Student("孙姬",20,159, 90)); //点击sort按F12 public void Sort(Comparison<T> comparison); // Sort(Comparison<Student> com) 默认传参的Sort方法 //继续F12 进入public delegate int Comparison<in T>(T x, T y); // Com(Student t1,Student t2) 然后把Com方法传给上面 list.Sort(HeightSort); //即 Sort(com); for (int i = 0; i < list.Count; i++) { Console.WriteLine(list[i]); } } public static int AgeSort(Student t1, Student t2) //年龄排序 { return t1.age - t2.age; } public static int HeightSort(Student t1, Student t2) //身高排序 { return t1.height - t2.height; } public static int WeightSort(Student t1, Student t2) //体重排序 { return t1.weight - t2.weight; }
匿名方法和lambda表达式
public delegate void Test1(); class Program { static void Main(string[] args) { Test1 t1 = new Test1(T1); //因为匿名函数没有名字,所以没有办法直接调用 //一般不会常用(反复使用的)的功能,可以用匿名函数 t1 += delegate () { Console.WriteLine("我是匿名函数"); }; //Lambda表达式用法 : 如果函数体只有一句话的时候,大括号可以省略 t1 += () =>Console.WriteLine("我是Lambda表达式"); t1(); Console.ReadKey(); } public static void T1() { Console.WriteLine("我是T1"); } }
多播委托
委托变量中存储了多个方法
调用委托变量,变量中存储的所有的方法都会执行
public delegate void TestDel(); static void Main(string[] args) { TestDel del = Func1; //将F2添加到del中 del += Func2; del += Func2; del += Func3; del -= Func2; del(); Console.ReadKey(); } static void Func1() { Console.WriteLine("F1"); } static void Func2() { Console.WriteLine("F2"); } static void Func3() { Console.WriteLine("F3"); } }
事件
特殊的委托类型的变量
使用了event关键字修饰的委托类型的变量就是事件
事件只能在定义事件的本类中调用,外部类只能对事件进行添加和删除方法
相比于委托变量更加安全
public delegate void Test(); //委托类型 public class Teacher { public string name; public Teacher(string name) { this.name = name; } public Test t; //委托类型的变量 public event Test DoThing; //有event关键字的委托类型的变量就是事件 public void Ding() { DoThing(); //事件不能在外面调用,只能再类里面写方法调用 } } class Program { static void Main(string[] args) { Teacher zhangsan = new Teacher("张三"); //事件特点:1、事件是类的成员,不能声明在类外,也不能声明在方法中; // 2、类外对事件直接赋值时不可以的,可以使用+= 、-=;(委托可以赋值也可以+=、-=) // 3、类外不能直接调用(执行)事件;委托可以再类外调用; zhangsan.DoThing += T1; zhangsan.Ding(); //zhangsan.t = T1; //zhangsan.t(); Console.ReadLine(); } public static void T1() { Console.WriteLine( "T"); } }