委托
委托是持有一个或多个方法的对象
例:根据返回的值执行持有的方法
delegate void MyDel(int value);//声明委托类型
class Program
{
void PrintLow(int value)
{
Console.WriteLine("{0}-low value",value );
}
void PrintHigh(int value)
{
Console.WriteLine("{0}-High value", value);
}
static void Main(string[] args)
{
Program program = new Program();
MyDel del;//声明委托变量
//创建随机整数生成器对象,并得到0到99之间的随机数
Random rand = new Random();
int randomValue = rand.Next(99);
//创建一个包含Print Low或Print High的委托对象并将其赋值给del变量
del = randomValue < 50
? new MyDel(program.PrintLow)
: new MyDel(program.PrintHigh);
del(randomValue);//执行委托
Console.ReadKey();
}
}
委托概述
委托和类一样,是一种用户自定义类型。但类表示的是数据和方法的集合,委托则持有一个或多个方法,以及一系列预定于操作。
使用委托步骤:
1.声明一个委托。
2.使用该委托类型声明一个委托变量。
3.创建委托类型的对象,把他赋值给委托变量。
4.可以为委托对象增加其他方法。
5.像调用方法一样调用委托。
委托保存的方法可以来自任何类或结构(返回类型和签名需一致)
声明委托类型
delegate void MyDel(int x);
关键字+返回类型+委托类型名+(签名);
委托类型声明没有方法的主体;
创建委托对象
声明变量:
MyDel delVar;
委托类型+变量;
创建委托对象:
1.使用new运算符: delVar=new MyDel(myInstObj.MyM1);
2.方法说明符构成:delVar=myInstObj.MyM1;
给委托赋值
由于委托是引用类型,我们可以通过给它赋值来改变包含在委托变量中的引用。旧的委托对象会被垃圾回收器回收。
组合委托
委托可以使用额外的运算符来组合。这个运算最终会创建一个新的委托。
MyDel delA=myInstObj.MyM1;
MyDel delB=SClass.OtherM2;
MyDel delC=delA+delB;
委托对象被创建后不能再被改变。
为委托添加和移除方法
添加:+=
移除:-=
添加方法加在调用列表底部;
移除方法从列表底部开始搜索,并且移除第一个与方法匹配的实例。
试图调用空委托会抛异常,我们可以通过把委托和null进行比较来判断委托的调用列表是否为空。
调用方法
像调用方法一样简单地调用委托。用于委托的参数将会用于调用调用列表中的每一个方法(除非有输出参数)。
如果一个方法在调用列表中多次出现,当委托被调用时,每次在列表中遇到这个方法都会被调用异常。
委托的示例
//定义一个没有返回值和参数的委托类型
delegate void PrintFunction();
class Test
{
public void Print1()
{
Console.WriteLine("Print1--instance");
}
public static void Print2()
{
Console.WriteLine("Print2--static");
}
}
class Program
{
static void Main(string[] args)
{
Test t = new Test();//创建一个测试类实例
PrintFunction pf;//创建一个空委托
pf = t.Print1;//实例化并初始化该委托
//给委托增加3个另外的方法
pf += Test.Print2;
pf += t.Print1;
pf += Test.Print2;
//现在,委托含有4个方法
if (pf != null)//确认委托有方法
{
pf(); //调用委托
}
else
{
Console.WriteLine("Delegate is empty");
}
Console.ReadKey();
}
}
调用带返回值的委托
调用列表中最后一个方法的返回的值就是委托调用返回的值
调用列表中所有其他方法的返回值都会被忽略
delegate int MyDel();//声明有返回值的方法
class MyClass
{
int IntValue=5;
public int Add2()
{
IntValue += 2;
return IntValue;
}
public int Add3()
{
IntValue += 3;
return IntValue;
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
MyDel mDel = mc.Add2;//创建并初始化委托
mDel += mc.Add3;//增加方法
mDel -= mc.Add2;//减去方法
Console.WriteLine("Value:{0}",mDel ());//最后一个方法执行的返回值是委托返回的值
Console.ReadKey();
}
}
调用带引用参数的委托
如果委托有参数引用,参数值会根据调用列表中的一个或多个方法的返回值而改变
delegate void MyDel(ref int X);
class MyClass
{
public void Add2(ref int X)
{
X += 2;
}
public void Add3(ref int X)
{
X += 3;
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
MyDel mDel = mc.Add2;//创建并初始化委托
mDel += mc.Add3;//增加方法
mDel -= mc.Add2;//减去方法
int x = 5;
mDel(ref x);
Console.WriteLine("Value:{0}", x);//引用参数的值会在调用间发生改变
Console.ReadKey();
}
匿名方法
匿名方法允许我们避免使用独立的具名方法;
匿名方法是在初始化委托时内联声明的方法
匿名方法的语法:
delegate(Parameters){ImplementationCoad}
关键字(参数列表){语句块}
class Program
{
delegate int OtherDel(int InParam);
static void Main(string[] args)
{
OtherDel del = delegate(int x)
{
return x + 20;//委托的返回类型是int,因此匿名方法也要返回int
};
//x=>x + 20;
Console.WriteLine("{0}",del (5));
Console.WriteLine("{0}", del(6));
Console.ReadKey();
}
//delegate void SomeDel(int X);//声明委托类型
//SomeDel SDel = delegate//省略的参数列表
//{
// PrintMessage();
// Cleanuo();
//};
delegate void SomeDel(int X,params int [] Y);
SomeDel SDel = delegate(int X, int [] Y)//匿名参数列表忽略params关键字
{
};
}
可以使用圆括号为空或省略圆括号来简化匿名方法的参数列表
委托的参数列表不包含任何out参
匿名方法不使用任何参数
变量和参数的作用域
参数以及声明在匿名方法内部的局部变量的作用域限制在实现方法的主体之内
匿名方法可以访问他们外围作用域的局部变量和环境。
外围作用域的变量叫做外部变量。
用在匿名方法实现代码中的外部变量称为方法捕捉。
class Program
{
delegate void MyDel();
static void Main(string[] args)
{
MyDel mDel;
{
int x = 5;//变量x定义在外部块中,在匿名方法之外
mDel = delegate
{
Console.WriteLine("Value of x:{0}", x);
};
}
//Console.WriteLine("Value of x:{0}", x);//变量x离开了作用域并且会导致编译错误
if (null != mDel)
mDel();//x在这里使用,在匿名方法内部
Console.ReadKey();
}
}
Lambda表达式
语法:参数部分=> Lambda主体
class Program
{
delegate int MyDel(int par);
static void Main(string[] args)
{
MyDel del = delegate(int X) { return X + 1; };//匿名方法
MyDel le1 = (int X) =>{ return X + 1; };//Lambda表达式
MyDel le2 = (X) => { return X + 1; };//省略类型参数
MyDel le3 = X => { return X + 1; };// 如果只有一个隐式类型参数,可以省略圆括号
MyDel le4 = X => X + 1;//Lambda表达式允许表达式的主体是语句块或表达式,如果包含返回语句,可以替换为return关键字后的表达式
Console.WriteLine("{0}", del(12));
Console.WriteLine("{0}", le1(12));
Console.WriteLine("{0}", le2(12));
Console.WriteLine("{0}", le3(12));
Console.WriteLine("{0}", le4(12));
Console.ReadKey();
}
}