------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
——委托
什么是委托:
委托是一种用于封装方法的类型,是一个能够引用方法的对象,能够调用它所指向的方法,在程序运行期间,同个委托可以调用不同的方法,委托是委托类型的实例
委托的基类:
System.Delegate类,其本身不是委托类型,且不允许显式的直接从该类派生新的类型
声明委托:
创建一个协定,该协定指定一个或多个方法的签名
引用静态方法或者实例方法
(声明委托需要使用delegate关键字
语法:
访问修饰符 delegate返回值类型(方法参数)
访问修饰符:
Public:表示该委托是公开的,访问不受限制
Protected:表示该委托只能是本身委托访问
Internal:表示该委托只能是在当前应用程序中访问
Private:表示该委托只能是本身访问
(注意:只有在其他类型中声明委托时,才能够使用new修饰符,它表示所声明的委托会隐藏具有相同名称的继承成员)
返回值类型:
返回值类型和传入的方法共同确定方法的返回类型,方法名,方法参数
例如:
publicdelegateintMyDelegate(int i,int j);//声明委托MyDelegate
(注意:委托类型是默认从System.Delegate派生的类类型,它隐含为密封类型化,因此不能从委托类型派生一个新的类型)
向委托注册方法:
委托声明好以后,就需要给委托添加方法列表,使得创建对象后可以依次执行各个方法
注册方法到委托时,该方法的签名必须和该委托的所指定的签名完全匹配
匹配规则:
a).方法返回类型必须和委托的返回类型相同
b).方法的方法参数必须和委托的的方法参数相同,参数的具体名称可以不相同
例如:
声明五个方法:F1,F2,F3,F4,F5,判断它们能否注册到MyDelegate委托中
publicvoid F1(int i, int j);//不能,原因:返回值类型与MyDelegate委托不相同
publicvoid F2(int i);//不能,原因:返回值类型和方法参数个数与MyDelegate委托不相同
publicint F3(int i);//不能,原因:方法参数个数与MyDelegate委托不同
publicint F4(int i,int j);//能
publicint F5(int j,int i);//能
实例化委托:
委托是一个类,因此,委托需要实例化。
委托实例化可以创建委托类型的实例,并向该实例注册方法列表
委托类型的实例的方法列表可以为静态方法,实例方法或者另外一个委托实例
(注意:委托实例化,它把静态方法,实例方法或者另外一个委托的名称作为该实例的参数进行传递)
例如:
namespace 实例化委托
{
public delegate int MyDelegate(int i);//声明一个委托:名称为MyDelegate返回类型为int,方法参数为int i
class Program//声明一个类:名称为Program,类中有一个实例方法F1(inti),一个静态方法F2(int i)
{
public int F1(int i)
{
Console.WriteLine("调用了一个实例方法F1(int i)");
return i;
}
public static int F2(int j)
{
Console.WriteLine("调用了一个静态方法F2(int j)");
return j;
}
static void Main(string[] args)
{
Program p = new Program();//实例化program类为p,
MyDelegate d1 = new MyDelegate(p.F1);//d1注册p的实例方法F1
int i = d1(10);
Console.WriteLine("i的值为" + i);
MyDelegate d2 = new MyDelegate(Program.F2);//d2注册program的静态方法F2
int j = d2(20);
Console.WriteLine("j的值为" + j);
}
}
}
结果:
构建委托的方法列表:
使用委托可以将多个方法绑定到同一个委托变量中。
当调用此变量时,可以一次调用所有绑定的方法。
每个委托实例都必须包含其方法列表,方法列个表可以包含一个或多个方法
委托实例除了在其实例化时注册方法之外,还可以通过“+”或”+=”运算符向该实例的方法列表中注册方法,通过“-”或者“-=”运算符从该实例的方法列表中移除方法
例如:
namespace test
{
public delegate int MyDelegate(int i);//声明一个委托:名称为MyDelegate返回类型为int,方法参数为int i
class Program//声明一个类:名称为Program,类中有两个静态方法F1(inti),F2(int i)
{
public static int F1(int i)
{
Console.WriteLine("调用了一个实例方法F1(int i)");
return i;
}
public static int F2(int i)
{
Console.WriteLine("调用了一个静态方法F2(int j)");
return i;
}
static void Main(string[] args)
{ //创建MyDelegate委托的5个实例:d1,d2,d3,d4,d5
MyDelegate d1 = new MyDelegate(Program.F1);//d1调用program类的F1方法
MyDelegate d2 = new MyDelegate(Program.F2);//d2调用program类的F2方法
MyDelegate d3 = d1 + d2;//d3一次调用program类的F1,F2方法
MyDelegate d4 = d1 + d2 + d3;//d4一次调用program类的F1,F2,F2,F1
MyDelegate d5 = d4 - d2;//d5一次调用program类的F1,F2,F1方法
int i1 = d1(20); Console.WriteLine("i1的值为" + i1);
int i2 = d2(20); Console.WriteLine("i2的值为" + i2);
int i3 = d3(20); Console.WriteLine("i3的值为" + i3);
int i4 = d4(20); Console.WriteLine("i4的值为" + i4);
int i5 = d5(20); Console.WriteLine("i5的值为" + i5);
Console.ReadKey();
}
}
结果:
分析:
d1和d2通过“+”运算符得到d3
d1,d2,d3通过“+”运算符得到d4
d4-d2得到d5,即表示从d4的方法列表的末端开始查找,如果该方法被包括在d2实例的方法列表中,则从d4的方法列表中移除该方法
调用委托:
委托是一个方法链条,因此调用我欸托实例就相当于调用了该委托实例包含的所有方法
如果一个调用列表包含多个方法时,当该委托实例被调用时,它将按照调用列表中方法的注册顺序依次调用每一个方法
例如:
namespace 构建委托的方法列表
{
public delegate void MyDelegate(int i);//声明一个委托:名称为MyDelegate,返回类型为void,方法参数为int i
class Program//声明一个类:名称为Program,内有两个静态方法F1(inti),F2(int i)
{
public static void F1(int i)//F1(int i):输出“Program.F1:参数i的值“
{
Console.WriteLine("Program.F1:" + i.ToString());
}
public static void F2(int i)//F2(inti):输出”Program.F2:参数i的值“
{
Console.WriteLine("Program.F2:" + i.ToString());
}
static void Main(string[] args)
{
MyDelegate d1 = new MyDelegate(Program.F1);//d1调用F1
MyDelegate d2 = new MyDelegate(Program.F2);//d2调用F2
MyDelegate d3 = d1 + d2;//d3依次调用F1,F2
MyDelegate d4 = d3 + d2 + d1;//d4一次调用 F1,F2,F2,F1
MyDelegate d5 = d4 - d2;//d5调用F1,F2,F1
d1(10); Console.WriteLine();
d2(200); Console.WriteLine();
d3(3000); Console.WriteLine();
d4(40000); Console.WriteLine();
d5(500000); Console.WriteLine();
Console.ReadKey();
}
}
结果:
分析:
d1(10);调用了d1实例,并调用和了F1方法。
d2(200);调用了d2实例,并调用了F2方法
d3(3000);调用了d3实例,并依次调用了F1,F2方法
d4(40000);调用了d4实例,并依次调用了F1,F2,F2,F1方法
d5(500000);调用了d5实例,并依次调用了F1,F2,F1方法
——事件
什么是事件:
某些操作发生时自动地放出的通知,它是一种信号机制
程序员可以通过提供事件处理程序,为相应的事件添加可执行代码。
当触发事件时,将调用该事件实现定义的方法
声明事件:
事件同委托一样,使用之前需要声明
它包含两个参数:指示事件源的”对象源“参数和封装事件的其他任何相关信息的e参数
其中e参数的类型为System.EventArgs或从System.EventArgs类派生的类型
步骤:声明事件的委托—>声明事件的本身
例如:
声明事件的委托:
1.EventHander包含两个参数:sender和e,其中sender表示事件源,e表示与该事件相关的信息
publicdelegatevoidEventHandler(object sender,EventArgs e);
声明事件的本身:
2.在类中声明事件Print,它的类型为EventHandler
publicevent EventHandler Print;
注册事件
事件同委托一样,需给事件注册方法列表
一个事件声明之后,该事件的默认值为null
如果希望该事件继续执行事先指定的操作,则首先向该事件注册方法列表(即委托的调用列表)
注册事件可以用”+=“运算符
例如:
namespace 注册事件
{
public delegate void EventHandler(object sender, EventArgs e);
class Program
{
public event EventHandler Print;//声明事件Print
public void F(object sender, EventArgs e)
{
Console.WriteLine("调用方法F");
}
static void Main(string[] args)
{
Program p = new Program();
p.Print += new EventHandler(p.F);
if (p.Print != null)//判断是否为空
{
p.Print(null, null);
}
Console.ReadKey();
}
}
}
移除事件
移除事件使用”-=“运算符来实现
例如:
namespace 移除事件
{
public delegate void EventHandler(object sender, EventArgs e);
class Program
{
public event EventHandler Print;//声明事件Print
public void F1(object sender, EventArgs e)
{
Console.WriteLine("调用方法F1");
}
public void F2(object sender, EventArgs e)
{
Console.WriteLine("调用方法F2");
}
static void Main(string[] args)
{
Program p = new Program();
p.Print += new EventHandler(p.F1);
p.Print += new EventHandler(p.F2);
if (p.Print != null)//判断是否为空
{
p.Print(null, null);
}
Console.WriteLine();
p.Print -= new EventHandler(p.F1);//移除F1事件
if (p.Print != null)//移除F1后的输出列表
{
p.Print(null, null);
}
Console.ReadKey();
}
}
}
调用事件
声明一个事件之后,如果没有向该事件注册方法,那么该事件的值为空(null)
因此,在调用事件时,往往需要检查该事件是否为空
例如:
namespace 调用事件
{
public delegate void EventHandler(object sender, EventArgs e);
class Program
{
public event EventHandler Print;//声明事件Print
public void F1(object sender, EventArgs e)
{
Console.WriteLine("调用方法F1");
}
static void Main(string[] args)
{
Program p = new Program();
p.Print += new EventHandler(p.F1);
Console.WriteLine("事件中的方法列表");
if (p.Print != null)//判断是否为空
{
p.Print(null, null);//调用事件
}
Console.ReadKey();
}
}
}
——委托和事件的关系
事件是一种特殊的委托