委托是持有一个或多个方法的对象。但委托与典型的对象不同,可以执行委托,这时委托会执行它所“持有”的方法
1.定义委托
delegate关键字 + 返回值的数据类型 +委托名
例:delegate string GetStr();//这一步就是声明委托类型
定义返回值为string的委托,委托名为GetStr
创建实例
如
int x=40;
//GetStr a=new GetStr(x.toString);//让a指向整形x中的toString方法
GetStr a=x.toString;//直接通过等号将方法赋值给委托对象
Console.WriteLine(a());//调用a()方法 实际就是引用了toString()方法
private delegate void PrintMed();
static void PrintStr(PrintMed med){ //函数中参数可以使用委托变量
med();//调用委托变量对应的方法(函数)
}
void Method1(){
Console.WriteLine("Method1");
}
void Method2(){
Console.WriteLine("Method2");
}
static void Main(String[] args){
PrintMed a=Method1;
PrintStr(a);//调用委托变量a中对应的方法Method1
a=Method2;//改变委托变量a的方法为Method2
PrintStr(a);//调用Method2方法
}
Action委托 一定无返回值 但可以传入参数Action
T为传入的数据类型
Func委托 必须有返回值 Func T代表返回的数据类型
也可以传入参数例如
Func<string,int> 最后一个类型是返回值类型,前面的类型是参数类型,参数类型必须跟指向的方法的参数类型按照顺序对应
2.给委托赋值
由于委托是引用类型,我们可以通过给它赋值来改变包含在委托变中的引用。旧的委托对象会被垃圾回收站回收
例:
void Test1(){}
void Test2(){}
...
Mydel delVar;//声明一个委托对象
delVar=Test1;
delVar=Test2;//此时执行delVar()只有Test2方法
3.给委托添加方法
上面我们知道委托是不变的,不过C#提供了看上去可以为委托添加方法的语法,即使用+=运算符
例:
class Program
{
static void Test1()
{
Console.WriteLine("输出Test1");
}
static void Test2()
{
Console.WriteLine("输出Test2");
}
static void Main(string[] args)
{
Action a = Test1;
a += Test2;
a += Test1;
a();
//Delegate[] delegates = a.GetInvocationList();//获取委托对象中包含的方法集合
//foreach(var de in delegates)
//{
// de.DynamicInvoke();//遍历实现方法
//}
Console.ReadKey();
}
}
其实由于委托是不可变的,所以为委托的调用列表添加2个方法后的结果其实是变量指向的一个全新的委托,最后再将这个新的委托赋值给我们创建的委托对象a
4.从委托移除方法
可以使用-=运算符从委托移除方法
与为委托增加方法一样,其实是创建了一个新的委托。新的委托是旧的委托的副本——只是没有了已经被移除方法的引用。
注意事项:1.如果在调用列表中的方法有多个实例,-=运算符将从列表最后开始搜索,并且移除第一个与方法匹配的实例。
2.试图删除委托中不存在的方法没有效果
3.试图调用空委托会抛出异常。可以通过把委托与null进行比较来判断委托的调用列表是否为空。如果调用列表为空,则委托是null。
5.匿名方法
匿名方法允许我们避免使用独立的具名方法,其实质就是在初始化委托时内联(inline)声明的方法。
使用地方:1.声明委托变量时作为初始化表达式。
2.组合委托时在赋值语句的右边。
3.为委托增加事件时在赋值语句的右边。
组成部分: delegate关键字+ (参数列表) +{语句块}
class Program
{
static void Main(string[] args)
{
Func<int, int, int> a = delegate (int a1, int a2)
{
return a1 + a2;
};
Console.WriteLine(a(2,3).ToString());
Console.ReadKey();
}
}
6.Lambda表示
C#2.0引入了匿名方法。然而它的语法有一点麻烦,而且需要一些编译器已经知道的消息。C#引入了Lambda表达式,简化了匿名方法的语法,从而避免包含这些多余的信息。
从匿名方法转换到Lambda表达式。
1.删除delegate关键字
2.在参数列表和匿名方法主体之间放Lambda运算符=> .读作"goes to"。
例:
Mydel del=delegate(int x) {return x+1;}//匿名方法
Mydel del= (int x)=>{return x+1;}//Lambda表达式
我们还可以进一步简化Lambda表达式。
编译器可以从委托的声明中知道委托参数的类型,因此Lambda表达式允许我们省略类型参数
Mydel del= (x)=>{return x+1;}//Lambda表达式
如果只有一个参数,我们可以省略周围的圆括号
Mydel del= x=>{return x+1;}//Lambda表达式
最后 Lambda表达式允许表达式的主体是语句块或表达式。如果语句块包含了一个返回语句,我们可以将语句块替换为return 关键字后的表达式
Mydel del= x=> x+1;//Lambda表达式
基础概念差不多就这些了吧…如果有遗漏的或者哪里写错了请指出谢谢