委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。
如何使用委托?
1、定义委托类型
[访问修饰符] delegate 返回类型 委托名(形参);
2、声明委托对象
委托名 委托实例名;
3、创建委托对象
委托实例名 = new 委托名(某个类的方法)
4、使用委托调用方法
委托实例名(实参)
委托注意事项:
1、委托和方法必须具有相同的签名。
2、委托可以调用多个方法,即一个委托对象可以维护一个可调用方法的列表而不是单独的一个方法,称为多路广播(多播)。
3、使用+=和-=运算实现方法的注册和注销
写法:
1、委托 委托名 = new 委托(会调用的方法名);
委托名(参数);
CallobjCall =newCall(SimpleMath.Multiply);
CallobjCall1 =newCall(newSimpleMath().Divide);
2、委托 委托名 = 会调用的方法名;
委托名(参数);
CallobjCall =SimpleMath.Multiply;
CallobjCall1 =newSimpleMath().Divide;
3、匿名方法
委托 委托名 = delegate(参数){会调用的方法体};
委托名(参数);
CallobjCall =delegate(inta,intb) { return a * b; };
CallobjCall1 =delegate(inta,intb) { returna / b; };
4、lambda表达式
委托 委托名 = ((参数1,。。参数n)=>{会调用的方法体});
委托名(参数);
CallobjCall = ((inta,intb) => {returna * b; });
CallobjCall1 = ((inta,intb) => {returna / b; });
5、用Action和Func,第一个无返回值
Func<参数1, 参数2, 返回值> 委托名 = ((参数1,参数2) => {带返回值的方法体 });
返回值 = 委托名(参数1,参数2);
Action obj = ((a, b) => {Console.WriteLine(a * b); });
obj(5, 3);
Func objCall = ((a, b) => {returna * b; });
intresult = objCall(5, 3);
Func objCall1 = ((a, b) => {returna / b; });
intresult1 = objCall1(5, 3);
1.委托的声明
(1). delegate
delegate是我们常用到的一种声明。
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。
例:public delegate int MethodtDelegate(int x, int y);表示有两个参数,并返回int型。
(2). Action
Action是无返回值的泛型委托。
Action表示无参,无返回值的委托。
Action 表示有传入参数int,string无返回值的委托。
Action 表示有传入参数int,string,bool无返回值的委托。
Action 表示有传入4个int型参数,无返回值的委托。
Action至少0个参数,至多16个参数,无返回值。
例:
public void Test(Action action,T p)
{
action(p);
}
(3). Func
Func是有返回值的泛型委托
Func 表示无参,返回值为int的委托
Func 表示传入参数为object,string 返回值为int的委托
Func 表示传入参数为T1,T2,T3(泛型)返回值为int的委托
Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void
例:
public int Test(Funcfunc,T1 a,T2 b)
{
return func(a, b);
}
(4) .predicate
predicate是返回bool型的泛型委托
predicate 表示传入参数为int 返回bool的委托
Predicate有且只有一个参数,返回值固定为bool
例:public delegate bool Predicate (T obj)
2.委托的使用
(1).Delegate的使用
public delegate int MethodDelegate(int x, int y);
private static MethodDelegate method;
static void Main(string[] args)
{
method = new MethodDelegate(Add);
Console.WriteLine(method(10,20));
Console.ReadKey();
}
private static int Add(int x, int y)
{
return x + y;
}
(2).Action的使用
static void Main(string[] args)
{
Test(Run,"Hello World!");
Test(Run, 1000);
//使用Lambda表达式定义委托
Test(p => { Console.WriteLine("{0}", p); }, "Hello World");
Console.ReadKey();
}
public static void Test(Action action, T p)
{
action(p);
}
private static void Run(string s)
{
Console.WriteLine(s);
}
private static void Run(int s)
{
Console.WriteLine(s);
}
可以使用 Action 委托以参数形式传递方法,而不用显式声明自定义的委托。
封装的方法必须与此委托定义的方法签名相对应。 也就是说,封装的方法必须具有四个均通过值传递给它的参数,并且不能返回值。
(3).Func的使用
static void Main(string[] args)
{
Console.WriteLine(Test(Run,100,200));
Console.ReadKey();
}
public static int Test(Func func, T1 a, T2 b)
{
return func(a, b);
}
private static int Run(int a, int b)
{
return a + b;
}
(4). predicate的使用
泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。
static void Main(string[] args)
{
Point[] points = { new Point(100, 200),
new Point(150, 250), new Point(250, 375),
new Point(275, 395), new Point(295, 450) };
Point first = Array.Find(points, Product);
Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
Console.ReadKey();
}
private static bool Product(Point p)
{
if (p.X * p.Y > 100000)
{
return true;
}
else
{
return false;
}
}
使用带有 Array.Find 方法的 Predicate 委托搜索 Point 结构的数组。如果 X 和 Y 字段的乘积大于 100,000,此委托表示的方法 ProductGT10 将返回 true。Find 方法为数组的每个元素调用此委托,在符合测试条件的第一个点处停止。
3.委托的清空
(1).在类中申明清空委托方法,依次循环去除委托引用。
方法如下:
public MethodDelegate OnDelegate;
public void ClearDelegate()
{
while (this.OnDelegate != null)
{
this.OnDelegate -= this.OnDelegate;
}
}
(2).如果在类中没有申明清空委托的方法,我们可以利用GetInvocationList查询出委托引用,然后进行去除。
方法如下:
public delegate void MethodDelegate();
public static MethodDelegate OnDelegate;
static void Main(string[] args)
{
if (OnDelegate != null)
{
Delegate[] dels = test.OnDelegate.GetInvocationList();
for (int i = 0; i < dels.Length; i++)
{
test.OnDelegate -= dels[i] as MethodDelegate;
}
}
}
4.委托的特点
委托类似于 C++ 函数指针,但它们是类型安全的。
委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以链接在一起;例如,可以对一个事件调用多个方法。
方法不必与委托签名完全匹配。
5.总结:
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型
Func可以接受0个至16个传入参数,必须具有返回值
Action可以接受0个至16个传入参数,无返回值
Predicate只能接受一个传入参数,返回值为bool类型