C#委托
2017-03-30 18:48
99 查看
如果我们要把方法当做参数来传递的话,就要用到委托,委托可以赋值一个方法的引用,然后通过委托变量去调用这个方法,定义委托就是告诉编译器这个委托可以指向哪些类型的方法,然后创建委托实例
定义委托的语法如下:
delegate void Test(int x);
这句话的意思是定义一个名字为Test的委托,这个委托可以指向一个参数为一个int类型的,返回值为void的方法。
定义委托要定义方法的参数和返回值,使用关键字delegate定义。
这里再举几个例子:
delegate int GetMax(int a,int b); delegate string Combine(string a,string b);
下面上几个完整的代码例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { private delegate string GetAString();//定义了一个委托GetAString static void Main(string[] args) { int x = 40; //使用委托创建实例 GetAString a = new GetAString(x.ToString);//a指向了x中的tostring方法 string s1 = a();//通过委托实例去调用x中的tostring方法(常用) GetAString b = x.ToString;//常用 string s2 = b.Invoke();//通过invoke方法去调用x的tostring方法 Console.WriteLine(s1); Console.WriteLine(s2); Console.ReadKey(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { delegate void PrintMes(); static void Print(PrintMes print){ print();//间接调用委托指向的方法 } static void Test1(){ Console.WriteLine("Test1"); } static void Test2(){ Console.WriteLine("Test2"); } static void Main(string[] args) { PrintMes pm = Test1; Print(pm);//委托作为参数传递 pm = Test2;//委托的实例就像变量一样可以更改所指向的引用 Print(pm); Console.ReadKey(); } } }
系统内置的委托类型Action:
Action是系统内置的一个委托类型,它可以指向一个没有返回值,有参数的方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { static void Test1(){ Console.WriteLine("Test1"); } static void Test2(int a){ Console.WriteLine("Test2"+a); } static void Main(string[] args) { Action a = Test1;//action是系统定义的无返回值的委托 Action<int> b = Test2;//通过泛型可以指向一个没有返回值有参数的方法,参数个数为泛型的个数,用','隔开,且类型顺序与方法参数类型必须一致 Console.ReadKey(); } } }
系统内置的委托类型Func:
Func是系统内置的一个委托类型,它可以指向一个有返回值,有参数的方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { static string Test1(){ return "Test1"; } static int GetRes(string a){ Console.WriteLine(a); return 100; } static void Main(string[] args) { Func<string> a = Test1;//Func也是系统定义的委托,使用泛型来指定方法的返回值类型 Func<string, int> b = GetRes;//Func可以指定多个泛型,最后一个泛型指定返回值类型,其它的为参数类型 Console.ReadKey(); } } }
多播委托:
调用委托就会调用多个方法,就像广播一样,多播委托只能得到调用的最后一个方法的结果,一般我们把多播委托的返回类型声明为void
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { static void Test1(){ Console.WriteLine("Test1"); bc81 } static void Test2(){ Console.WriteLine("Test2"); } static void Main(string[] args) { Action a = Test1; a += Test2;//使用+号将方法串联起来 a(); a -= Test1;//将Test1方法移除 a();//如果委托为空,调用的时候就会报错,所有一般都会先判断空 Delegate[] delegates = a.GetInvocationList();//得到委托所调用的方法集合 foreach(Delegate d in delegates){ d.DynamicInvoke();//单独调用方法,如果方法有参数,直接写在DynamicInvoke()括号里 } } } }
匿名方法:
匿名方法就是没有名字的方法,所以调用的时候只能赋值给委托去调用了
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { static void Main(string[] args) { //匿名方法 Func<int,int,int> a = delegate(int arg1,int arg2) { return agr1+arg2; }; } } }
Lambda表达式:
lambda表达式是用来代替匿名方法的,所以一个lambda表达式也是定义了一个方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { static void Main(string[] args) { //lambda表达式可以不用delegate关键字,和参数变量类型 Func<int,int,int> plus = (arg1,arg2)=> { return arg1+arg2; }; Func<int,int> test = a=>a+1;//lambda表达式如果参数为一个则可以去掉括号,当函数体只有一句话时可以不加上大括号和return语句,编译器会自动添加return语句 } } }
事件:
在委托前面加上event后便成了事件,事件的基本用法与委托基本一样,区别在于,事件不能在类外触发
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyDelegate { class Program { public delegate void TestDelegate(); public event TestDelegate testDelegate;//声明事件 static void Main(string[] args) { } } }