委托(Delegate)
什么是委托?
使用委托就是可以把方法当做变量使用
在C语言中 函数指针是指向一个函数的地址 函数指针变量可以作为一个参数进行传递 在C#中可以将委托类比成C语言中的函数指针 将可变的操作当做参数传入方法中进行调用
委托声明
声明委托变量之前要声明委托类型 用来指定方法签名(委托返回类型 参数列表)的信息 这里声明了几种不同的委托类型
/// <summary>
/// 参数类型为object的委托类型
/// </summary>
/// <param name="objPara"></param>
public delegate void InputObjDelegate(object objPara);
/// <summary>
/// 参数类型为string的委托类型
/// </summary>
/// <param name="strPara"></param>
public delegate void InputStrDelegate(string strPara);
/// <summary>
/// 参数类型为int的委托类型
/// </summary>
/// <param name="intPara"></param>
public delegate void InputIntDelegate(int intPara);
/// <summary>
/// 返回类型为object的委托类型
/// </summary>
/// <returns></returns>
public delegate object OutputObjDelegate();
/// <summary>
/// 返回类型为int的委托类型
/// </summary>
/// <returns></returns>
public delegate int OutputIntDelegate();
定义一个类用于展示委托的使用 在类中提供了几个实例方法与静态方法用于委托实例化 (MyPrint类)
public class MyPrint
{
/// <summary>
/// 打印object静态方法
/// </summary>
/// <param name="objPara"></param>
public static void StaticPrintObject(object objPara)
{
Console.WriteLine("打印object静态方法:" + objPara);
}
/// <summary>
/// 打印string静态方法
/// </summary>
/// <param name="strPara"></param>
public static void StaticPrintStr(string strPara)
{
Console.WriteLine("打印string静态方法:" + strPara);
}
/// <summary>
/// 返回类型为string静态方法
/// </summary>
/// <returns></returns>
public static string StaticReturnStr()
{
Console.WriteLine("返回string静态方法");
return "返回string静态方法";
}
/// <summary>
/// 返回类型为Int静态方法
/// </summary>
/// <returns></returns>
public static int StaticReturnInt()
{
Console.WriteLine("返回Int静态方法");
return 0;
}
#【c#心得记录】委托细节一#
/// <summary>
/// 打印string方法
/// </summary>
/// <param name="strPara"></param>
public void PrintStr(string strPara)
{
Console.WriteLine("打印string方法:" + strPara);
}
/// <summary>
/// 返回类型为string方法
/// </summary>
/// <returns></returns>
public string ReturnStr()
{
Console.WriteLine("返回string静态方法");
return "返回string静态方法";
}
}
委托的实列化
C#1.0版本委托的实例化与类一样 使用new关键字 构造的时候需要传参数类型数完全相同的方法 非静态方法需要首先实例化对象 使用实例化对象传入方法 静态方法需要使用类名传入方法
MyPrint myPrint = new MyPrint();
InputStrDelegate delInStr = new InputStrDelegate(myPrint.PrintStr);//非静态方法实例化
delInStr = new InputStrDelegate(MyPrint.StaticPrintStr);//静态方法实例化
C#2.0版本提供了匿名方法 方法组转换 可以使用这两种语法进行委托实例化
//匿名方法实例化
delInStr = delegate (string strPara)
{
return;
};
delInStr = MyPrint.StaticPrintStr;//方法组转换实例化
使用省略参数的匿名方法实例化委托时 这种省略参数的匿名方法可以转换为具有任何参数列表的委托类型
C#3.0版本使用lambda 表达式进行委托实例化 也不支持参数省略的功能
//lambda表达式实例化
delInStr = (p) =>
{
Console.WriteLine("委托实例化:lambda表达式");
};
委托的调用
委托调用分为同步调用与异步调用 首先实例化一个委托用于委托调用
InputStrDelegate delInStrInvoke = (p) =>
{
Console.WriteLine("委托调用");
};
同步调用
使用委托实例的Invoke方法可以进行委托的同步调用 参数列表与委托相同
delInStrInvoke.Invoke("参数");
C#为我们提供了另一种方式 可以使用更简单的方式进行调用 就像正常调用方法一样
delInStrInvoke("参数");
异步调用
使用委托实例的BeginInvoke方法可以进行委托的异步调用 该方法会使用一个后台线程进行异步的操作 参数列表中除去最后两个之外 与委托参数列表相同 最后两个参数分别传入回调方法 异步状态值(不使用可以传入null)
//AsyncCallback参数传入回调方法(委托)
//object参数传入回调State参数 回调方法中使用IAsyncResult参数类型的AsyncState属性获取
//后台线程
IAsyncResult asyncResult = delInStrInvoke.BeginInvoke("参数",
(p) =>
{
Console.WriteLine(p.AsyncState);
},
"回调State参数");
异步调用状态/结果有以下几种处理方式
while(!asyncResult.IsCompleted) { };//IsCompleted判断操作是否完成
asyncResult.AsyncWaitHandle.WaitOne();//阻塞等待操作完成
delInStrInvoke.EndInvoke(asyncResult);//阻塞等待操作完成 获取返回类型值