第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");
        }
    }
原文地址:https://www.cnblogs.com/yifengs/p/14117929.html