委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。委托类型有:delegate、Action、Func、Predicate。事件是一种特殊的委托。
1、委托的声明1.1、Delegate 是常用到的一种声明。至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。例如,表示有两个参数,并返回int型。
///1.2、Action 无返回值的泛型委托。/// 两数相乘的委托/// public delegate ResultT MultiplyDelegate(T1 x, T2 y);class Program { private static MultiplyDelegate multiplyDelegate; static void Main(string[] args) { multiplyDelegate += Multiply;//或者:multiplyDelegate=new MultiplyDelegate (Multiply); Console.WriteLine(multiplyDelegate(10, 20)); } private static int Multiply(int x,int y) { return x * y; } }
Action 表示无参,无返回值的委托
Action
表示有传入参数int,string无返回值的委托 Action
表示有传入参数int,string,bool无返回值的委托 Action
表示有传入4个int型参数,无返回值的委托
Action至少0个参数,至多16个参数,无返回值。
static void Main(string[] args)
{
InvokeAction( new Action(ShowString),"字符串Action委托");
InvokeAction(new Action(ShowDouble), 9.09);
InvokeAction(p=> { Console.WriteLine(p); }, "Lambda表达式委托");
}private static void InvokeAction(Action action,T t)
{
action.Invoke(t);
}private static void ShowString(string s)
{
Console.WriteLine(s);
}private static void ShowDouble(double d)
{
Console.WriteLine(d);
} 1.3、Func 有返回值的泛型委托Func
表示无参,返回值为int的委托 Func
Func
Func
表示传入参数为T1,T2,,T3(泛型)返回值为int的委托
Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可是void。
class Program
{ static void Main(string[] args)
{
Func func = new Func(Multiply);
Console.WriteLine(func(10, 20));
} private static int Multiply(int x,int y)
{ return x * y;
}
} 可以使用 Action
Predicate
static void Main(string[] args)
{
Tuple tuple1 = new Tuple(89, 34);
Tuple tuple2 = new Tuple(12, 34);
Tuple tuple3 = new Tuple(125, 30);
Tuple tuple4= new Tuple(192, 340);
Tuple[] tuples = new Tuple[] { tuple1, tuple2, tuple3, tuple4 };
Tuple frist = Array.Find(tuples, Product);
Console.WriteLine(frist.ToString());
}private static bool Product(Tuple tuple)
{ return tuple.Item1> tuple.Item2;
} 使用带有 Array.Find 方法的 Predicate 委托搜索 Tuple
前面使用到的委托都只包含了一个方法的调用。调用委托的次数与调用方法的次数相同。如果要调用多个方法,需要多次显示调用该方法---多播委托。多播委托的签名必须返回void,否则只能获取到最后一个方法的结果。多播委托使用前面的“multiplyDelegate += Multiply”形式实现添加多个委托方法。如果正在使用多播委托,对同一委托调用方法链的顺序并未正式定义,因此应该避免编写依赖于以特定顺序调用方法的代码。
多播委托可能出现调用方法停止问题。如果委托方法中的某一个方法抛出异常,整个迭代就会停止,未执行的方法便不会执行。定义两个方法One()与Two(),其中One()方法中会抛出一个异常
private static void One()
{
Console.WriteLine("One"); throw new Exception("One");
}private static void Two()
{
Console.WriteLine("Two");
}在Main()方法中创建一个委托d,引用One和Two方法。调用委托d,并使用try……catch捕获异常:
static void Main(string[] args)
{
Action d = One;
d += Two; try
{
d();
} catch(Exception e)
{
Console.WriteLine(e.Message);
}
}解决多播委托的异常导致整个迭代方法停止问题,便需要有自己的迭代方法。使用Delegate类定义GetInvocationList()方法获取添加到委托的Delegate对象数组,使用循环迭代、捕获异常即可:
static void Main(string[] args)
{
Action d = One;
d += Two;
Delegate[] delegates = d.GetInvocationList(); foreach (Action item in delegates)
{ try
{
item();
} catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
} 3、委托的清空委托的添加可以像前面使用“+”符号添加,同样的可以使用“-”符号来减少委托。也可以对委托重新赋值为null,清空所有委托。
4、委托的优点委托类似于 C++ 函数指针,但它们是类型安全的
委托允许将方法作为参数进行传递
委托可用于定义回调方法
委托可以链接在一起;例如,可以对一个事件调用多个方法
方法不必与委托签名完全匹配
原文出处



