• 第19天C#委托和事件


    委托

    概念

    自定义的类型,与结构体、枚举、类都是自定义类型

    委托的使用

    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");
            }
        }
  • 相关阅读:
    P6585 中子衰变
    [APIO2020]有趣的旅途
    CF1354F Summoning Minions
    CF1361C Johnny and Megan's Necklace
    CF1368E Ski Accidents
    CF1458C Latin Square
    CF1368F Lamps on a Circle
    用户和组的管理
    Windows命令
    1
  • 原文地址:https://www.cnblogs.com/yifengs/p/14117929.html
Copyright © 2020-2023  润新知