委托应用及泛型委托和多播委托

一、委托一般作为方法的参数或者返回值,或者使用多播委托(注册多个方法,可以全部触发)

1.示例:根据对于字符串不同的处理方法逻辑
      private delegate void PrintString(string str);

        static void PrintStr( PrintString print,string str )
        {
            print(str);
        }

        static void Method1(string str) {
            Console.WriteLine(str);
        }
        static void Method2(string str)
        {
            Debug.WriteLine(str);
        }
 static void Main(string[] args)
{

           PrintString method = Method1;
            PrintStr(method,"Test");
            method = Method2;
            PrintStr(method,"Test");
            Console.ReadKey();

}

二、泛型委托

Action-Action<T>

   class Program {
        static void PrintString()
        {
            Console.WriteLine("hello world.");
        }

        static void PrintInt(int i)
        {
            Console.WriteLine(i);
        }

        static void PrintString(string str)
        {
            Console.WriteLine(str);
        }

        static void PrintDoubleInt(int i1, int i2)
        {
            Console.WriteLine(i1+i2);
        }
        static void Main(string[] args)
        {
            //Action a = PrintString;//action是系统内置(预定义)的一个委托类型,它可以指向一个没有返回值,没有参数的方法
            //Action<int> a=PrintInt;//定义了一个委托类型,这个类型可以指向一个没有返回值,有一个int参数的方法
            //Action<string> a = PrintString;//定义了一个委托类型,这个类型可以指向一个没有返回值,有一个string参数的方法 在这里系统会自动寻找匹配的方法
            Action<int, int> a = PrintDoubleInt;
            a(34, 23);
            Console.ReadKey();
            //action可以后面通过泛型去指定action指向的方法的多个参数的类型 ,参数的类型跟action后面声明的委托类型是对应着的
           
        }
    }

Func<T>  

  class Program {
        static int Test1()
        {
            return 1;
        }

        static int Test2(string str)
        {
            Console.WriteLine(str);
            return 100;
        }

        static int Test3(int i, int j)
        {
            return i + j;
        }
        static void Main(string[] args)
        {
            //Func<int> a = Test1;//func中的泛型类型制定的是 方法的返回值类型
            //Console.WriteLine(a());
            //Func<string, int> a = Test2;//func后面可以跟很多类型,最后一个类型是返回值类型,前面的类型是参数类型,参数类型必须跟指向的方法的参数类型按照顺序对应
            Func<int, int, int> a = Test3;//func后面必须指定一个返回值类型,参数类型可以有0-16个,先写参数类型,最后一个是返回值类型
            int res = a(1, 5);
            Console.WriteLine(res);
            Console.ReadKey();
        }
    }

泛型委托应用:冒泡排序扩展

class Employee {
        public string Name { get; private set; }
        public int Salary { get; private set; }

        public Employee(string name, int salary)
        {
            this.Name = name;
            this.Salary = salary;
        }
        //如果e1大于e2的话,返回true,否则返回false
        public static bool Compare(Employee e1, Employee e2)
        {
            if (e1.Salary > e2.Salary) return true;
            return false;
        }

        public override string ToString()
        {
            return Name + ":" + Salary;
        }
    }
View Code
   class Program {
        static void Sort(int[] sortArray)
        {
            bool swapped = true;
            do
            {
                swapped = false;
                for (int i = 0; i < sortArray.Length - 1; i++)
                {
                    if (sortArray[i] > sortArray[i + 1])
                    {
                        int temp = sortArray[i];
                        sortArray[i] = sortArray[i + 1];
                        sortArray[i + 1] = temp;
                        swapped = true;
                    }
                }
            } while (swapped);
        }

        static void CommonSort<T>(T[] sortArray, Func<T,T,bool>  compareMethod)
        {
            bool swapped = true;
            do {
                swapped = false;
                for (int i = 0; i < sortArray.Length - 1; i++) {
                    if (compareMethod(sortArray[i],sortArray[i+1])) {
                        T temp = sortArray[i];
                        sortArray[i] = sortArray[i + 1];
                        sortArray[i + 1] = temp;
                        swapped = true;
                    }
                }
            } while (swapped);
        }
        static void Main(string[] args) {
            //int[] sortArray = new int[]{123,23,12,3,345,43,53,4};
            //Sort(sortArray);
            //foreach (var temp in sortArray)
            //{
            //    Console.Write(temp+" ");
            //}
            Employee[] employees = new Employee[]
            {
                new Employee("dsf",12), 
                new Employee("435dsf",234), 
                new Employee("234dsf",14), 
                new Employee("ds234f",234), 
                new Employee("dssfdf",90)
            };
            CommonSort<Employee>(employees,Employee.Compare);
            foreach (Employee em in employees)
            {
                Console.WriteLine(em);
            }
            Console.ReadKey();
        }
    }
View Code

多播委托:(可以注册多个方法给委托,也可以注销已注册的方法)

方法:

     static void T1()
        {
            Console.WriteLine("ok");
        }
        static void T2()
        {
            Console.WriteLine("ook");
        }
        static void T3()
        {
            Console.WriteLine("oook");
        }
        static void M1(string msg)
        {
            Console.WriteLine(msg);
        }
        static void M2(string msg)
        {
            Console.WriteLine(msg);
        }
        static void M3(string msg)
        {
            Console.WriteLine(msg);
            Console.WriteLine("第3个方法。。");
        }
        static void M4(string msg)
        {
            Console.WriteLine(msg);
        }
        static void M5(string msg)
        {
            Console.WriteLine(msg);
        }
View Code

示例:

 class Program
    {
        static void Main(string[] args)
        {
            #region 多播委托

            ////一般第一个要使用=赋值,后续的方法可以使用+=来赋值。
            //Action<string> action = M1;
            //action += M2; //表示添加一个委托的引用 
            //action += M3;
            //action += M4;
            //action += M5;//action -= M3;//表示去除一个委托的引用
            if(action!=null){//防止为空,报错
             action("xxx");//一次性触发全部的方法。调用顺序不一定哦。
}
//Console.ReadKey(); #endregion MyDelegate md = new MyDelegate(T1); //为什么这么写呢?等下取消注释上面的代码反编译之后放截图就知道 md = (MyDelegate)Delegate.Combine(md, new MyDelegate(T2), new MyDelegate(T3)); // md(); 下面的方法是获取所有注册的方法逐个调用 Delegate[] delegates = md.GetInvocationList(); for (int i = 0; i < delegates.Length; i++) { (delegates[i] as MyDelegate)(); } Console.ReadKey(); //使用队列试试 //Queue<MyDelegate> queue = new Queue<MyDelegate>(); //queue.Enqueue(new MyDelegate(T1)); //queue.Enqueue(T2); //queue.Enqueue(T3); //queue.Dequeue(); //queue.Dequeue(); //queue.Dequeue(); }

多播委托反编译:可看到,本质就是调用Delegate.Combine方法组装起来的,调用的时候为什么能全部触发已注册的方法?可以看到编译器调用GetInvocationList方法之后得到委托父类数组循环逐个调用; 事件的本质我们稍后探讨,跟多播密不可分

原文地址:https://www.cnblogs.com/entclark/p/7966765.html