【6月日新计划34】WPF入门-委託

126 阅读2分钟

blog.csdn.net/qq_39847278…

1. Introduction

1.委托⽤于将⽅法作为参数传递给其他⽅法,当于是对具有相同返回类型和参数列表这一类方法进行了封装

2.用关键字delegate 聲明的就是委托

    public class TrustFunction 
    {
        public delegate void ShowDelegate();

        public void Show()
        {
            System.Diagnostics.Trace.WriteLine("test");
        }

        public delegate string ShowStringDelegate(string str);

        public string ShowString(string str)
        {
            return str + "test";
        }

    }

1.1 Instance

  //舊寫法
  ShowDelegate showDelegate = new ShowDelegate(test.Show);
  //新寫法
  ShowDelegate showDelegate = test.Show;
  //匿名寫法
   ShowDelegate showDelegate = delegate ()
   {
         Console.WriteLine("匿名委托");
   };

  //Lambda寫法
   ShowDelegate2 showDelegate2 = (string s, int v) => { Console.WriteLine($"{s}&{v}"); };
   showDelegate2("s",2);

1.2 Advance

    public class DelegateTest
    {
        // 1.无参数无返回值委托
        public delegate void NoReturnNoPara();

        // 2.有参数无返回值委托
        public delegate void NoReturnWithPara(int x, int y);

        // 3.无参数有返回值的委托
        public delegate int WithReturnNoPara();

        // 4.带参数带返回值的委托
        public delegate int WithReturnWithPara(out int x, out int y);
    }
 class Program
    {

        private static void NoReturnNoParaMethod()
        {
            Console.WriteLine("无参数,无返回值的方法");
        }

        private static void NoReturnWithParaMethod(int s, int t)
        {
            Console.WriteLine("有参数,无返回值的方法");
        }

        static void Main(string[] args)
        {

            DelegateTest.NoReturnNoPara noReturnNoPara= new DelegateTest.NoReturnNoPara(NoReturnNoParaMethod);

            //使用赋值的方式实例
            DelegateTest.NoReturnWithPara noReturnWithPara = NoReturnWithParaMethod;

            //使用匿名委托实例
            DelegateTest.WithReturnNoPara withReturnNoPara = delegate() 
            {
                Console.WriteLine("无参数,有返回值的方法");
                return default(int);
            };

            //使用lambda 匿名方法实例
            DelegateTest.WithReturnWithPara WithReturnWithPara = (out int x, out int y) =>
            {
                x = 1;
                y = 2;
                Console.WriteLine("有参数,有返回值的方法");
                return x + y;
            };

            //调用委托
            noReturnNoPara();

            //使用invoke调用
            noReturnNoPara.Invoke();

            //调用有返回值,无参数的委托
            int result= withReturnNoPara.Invoke();

            //调用有返回值,有参数的委托
            int x1, y1;
            int result2 = WithReturnWithPara.Invoke(out x1,out y1);

            //使用BeginInvoke,开启一个线程去执行委托,NetCore不支持,NetFamework支持
            noReturnWithPara.BeginInvoke(1,2,null,null);
            
            //EndInvoke等待BeginInvoke方法执行完成后再执行EndInvoke后面的代码
            noReturnWithPara.EndInvoke();
            
            Console.ReadLine();
        }
    }

2. 委託鏈

  • 委托都是继承自MulticastDelegate(多播委托),定义的所有的委托都是多播委托
  • 可以通过+=把多个方法添加到这个委托中,形成一个方法的执行链,执行委托的时候,按照添加方法的顺序,依次去执行方法,
  • 可以通过-=把加入到委托中的方法注销
  • action.BeginInvoke();会开启一个新的线程 去执行委托,注册有多个方法的委托,不能使用BeginInvoke
  • 注册有多个方法的委托想要开启新线程去执行委托,可以通过action.GetInvocationList()获取到所有的委托,然后循环,每个方法执行的时候可以BeginInvoke

2.1 Demo

老師讓學生去買東西

    public class Student
    {
        public delegate void BuySomethingDelegate();

        public void BuyWater()
        {
            Console.WriteLine("买水!");
        }
        public void BuyKFC()
        {
            Console.WriteLine("买肯德基");
        }
        public void BuyHotDog()
        {
            Console.WriteLine("买热狗");
        }
    }

老師讓學生去買水

    Student stu = new Student();
    BuySomethingDelegate bsd = new BuySomethingDelegate(stu.BuyWater);
    bsd.Invoke();

老師讓學生去買水後,又去買熱狗和漢堡,發現錢不夠,又把熱狗退掉了。

    Student stu = new Student();
    BuySomethingDelegate bsd = new BuySomethingDelegate(stu.BuyWater);
    bsd += stu.BuyHotDog;
    bsd += stu.BuyKFC;
    bsd -= stu.BuyHotDog;
    bsd.Invoke();

2.2 擴展

使用多播委托的时候可能会遇到一个问题,當第一个方法报错了,导致后面的注册的方法都无法调用

   //获取委托链上的调用列表,返回的是委托数组
   Delegate[] delegateArr= bsd.GetInvocationList();
   foreach (BuySomethingDelegate item in delegateArr)
   {
         try
         {                    
             item.Invoke();
         }
         catch (Exception)
         {
              Console.WriteLine($"{item.Method.Name}方法报错了!");
         }
  }

如何取出里面返回值

   #如果BuySomethingDelegate 是有返回值的委托,
   Delegate[] delegateArr= bsd.GetInvocationList();
   foreach (BuySomethingDelegate item in delegateArr)
   {
         try
         {                    
            int result= item.Invoke();
         }
         catch (Exception)
         {
              Console.WriteLine($"{item.Method.Name}方法报错了!");
         }
   }

判断调用的委托是否为空,加加減減可能為空,为空则不会执行,不为空才会执行

    Student stu = new Student();
    BuySomethingDelegate bsd = new BuySomethingDelegate(stu.BuyWater);
    bsd += stu.BuyHotDog;
    bsd += stu.BuyKFC;
    bsd -= stu.BuyHotDog;
    bsd?.Invoke();

3. 泛型

3.1 泛型委託

    //定义了具有两个泛型参数类型的委托
    public delegate void CustomDelegate<T, V>(T t, V v);

    public class TestCustomDelegate
    {
        //聲明委托变量
        CustomDelegate<string, string> customDelegate;
        //编写与委托对应的方法
        public void TestMethod(string a,string b)
        {
            Console.WriteLine($"{a}拼接{b}");
        }

        public void Result()
        {
            //多種實例化方法
            customDelegate = TestMethod;
            customDelegate = new CustomDelegate<string, string>(TestMethod);
            customDelegate = delegate (string a1, string b1) { Console.WriteLine("delegate匿名方法也可以"); };
            customDelegate = (string a2, string b2) => { Console.WriteLine("使用lambda匿名方法"); };
            
            //执行委托
            customDelegate("test1","test2");
            customDelegate.Invoke("test1", "test2");
        }
    }

3.2 Action

  • Action 表示无参,无返回值的委托

  • Action<int,string> 表示有参,无返回值的泛型委托,最多可入参16个

  • 使用Action 就可以囊括所有无返回值委托,可以说Action事对无返回值委托的进一步包装

    public class ActionTest
    {
        public Action action;
        public void SendMsg()
        {
            Console.WriteLine("消息完成发送");
        }
        public void Test()
        {
           //实例化方式有四种,如下
            action = SendMsg;
            action = new Action(SendMsg);
            action = delegate(){ Console.WriteLine("delegate 匿名方法"); };
            action = () => { Console.WriteLine("lambda 匿名方法"); };
            
            //调用方式
	    action();
            action.Invoke();
        }
   }

3.2 Func

  • Func 表示有返回值的委托(必须有返回值)

  • Func可以无参数,也可以有参数,最多16个参数,最后一个表示返回值且只有一个

  • 使用方法同delegate,Func不过是对所有的有返回值的数据进行了一个包装

    public class FuncTest
    {
        public Func<int,int> func;
        public int DoubleNumber(int number)
        {
            Console.WriteLine("计算完成");
            return number * 2;
        }
        public void Test()
        {
            //实例化有以下4种方式
            func = DoubleNumber;
            func = new Func<int, int>(DoubleNumber);
            func = delegate (int a) 
            {
                Console.WriteLine("delegate 匿名方法");
                return a * 2 ;
            };
            func = (int b) => 
            {
                Console.WriteLine("lambda 匿名方法");
                return b * 2;
            };

            //调用
            int result = func(10);
            int result2 = func.Invoke(10);
        }
    }