C#编程之委托
一、委托的分类
1、Func:可以传递0或者多到16个参数类型,还可以传递一个返回值,并且返回值要放在参数最后。(有返回值)
2、Action:可以传递0或者多到16个参数类型,但是不可以传递返回值。(无返回值)
二、委托的定义
如果我们要把方法当做参数来传递的话,就要用到委托。简单来说委托是一个类型,这个类型可以赋值一个方法的引用。
三、Func的使用案例
方法:
/// <summary>
/// 从服务器下载文件,并将文件保存到本地
/// </summary>
/// <param name="url"></param>
/// <param name="parameters"></param>
/// <param name="method"></param>
/// <param name="filePath"></param>
/// <param name="fileName"></param>
/// <returns></returns>
public static string DownFile2HTTP2(string url, IDictionary<string, string> parameters, string method, string filePath, string fileName)
{
string path = filePath + "\\" + fileName;
if (method.ToLower() == "post")
{
FileStream fileStream = null;
HttpWebRequest req = null;
HttpWebResponse rsp = null;
System.IO.Stream reqStream = null;
try
{
fileStream = new FileStream(path, FileMode.Create);
req = (HttpWebRequest)WebRequest.Create(url);
req.Method = method;
req.KeepAlive = false;
req.ProtocolVersion = HttpVersion.Version10;
req.Timeout = 5000;
req.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
byte[] postData = Encoding.UTF8.GetBytes(BuildQuery(parameters, "utf8"));
reqStream = req.GetRequestStream();
reqStream.Write(postData, 0, postData.Length);
rsp = (HttpWebResponse)req.GetResponse();
byte[] data = new byte[1024];
while (true)
{
int length = reqStream.Read(data, 0, data.Length);
if (length == 0)
{
break;
}
else
{
fileStream.Write(data,0,length);
}
}
return "";
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
if (reqStream != null) reqStream.Close();
if (rsp != null) rsp.Close();
if (fileStream != null) fileStream.Close();
}
}
else
{
FileStream fileStream = new FileStream(path,FileMode.Create);
//创建请求
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "?" + BuildQuery(parameters, "utf8"));
//GET请求
request.Method = "GET";
request.ReadWriteTimeout = 5000;
request.ContentType = "text/html;charset=UTF-8";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
//写入文件
byte[] data = new byte[1024];
while (true)
{
int length = myResponseStream.Read(data, 0, data.Length);
if (length == 0)
{
break;
}
else
{
fileStream.Write(data, 0, length);
}
}
return "";
}
}
使用案例:
IDictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("name", "test");
//定义Func委托
Func<string, IDictionary<string, string>, string, string, string, string> func = HttpTools.DownFile2HTTP2;
//使用Func委托,IAsyncResult为Func的返回值类,用于判断方法是否执行完毕,以及后面获取返回值
IAsyncResult iAsyncResult = func.BeginInvoke("http://localhost:8080/web/", parameters, "GET", @"E:\work\HttpTest", "数据测试1.xls", null, null);
//通过死循环判断方法是否已执行完毕,验证方法是否完成
while (true)
{
if (iAsyncResult.IsCompleted)
{
break;
}
}
//通过EndInvoke方法获取返回值,参数类型为开始执行委托时的返回值
string result = func.EndInvoke(iAsyncResult);
四、Aciton的使用案例
方法:
private void GetMessage(string name,int a,int b)
{
int sum = a + b;
Debug.WriteLine(name + ": " + sum);
}
案例:
//定义Action委托
Action<string,int,int> action = GetMessage;
//使用Action委托
IAsyncResult result = action.BeginInvoke("zhangsan", 10, 12,null,null);
//通过死循环判断方法是否已执行完毕,验证方法是否完成
while (true)
{
if (result.IsCompleted)
{
break;
}
}
五、委托的其他使用案例之排序
//类的定义
class Employee{
public Employ(string name,decimal salary){
this.Name = name;
this.Salary = salary;
}
public string Name{get;private set;}
public decimal Salary{get;private set;}
public static bool CompareSalary(Employee e1,Employee e2){
return e1.salary>e2.salary;
}
}
//排序方法
public static void Sort<T>( List<T> sortArray,Func<T,T,bool> comparision ){
bool swapped = true;
do{
swapped = false;
for(int i=0;i<sortArray.Count-1;i++){
if(comparision(sortArray[i+1],sortArray[i])){
T temp = sortArray[i];
sortArray[i]=sortArray[i+1];
sortArray[i+1]=temp;
swapped = true;
}
}
}while(swapped);
}
//使用案例
static void Main(){
Employee[] employees = {
new Employee("Bunny",20000),
new Employee("Bunny",10000),
new Employee("Bunny",25000),
new Employee("Bunny",100000),
new Employee("Bunny",23000),
new Employee("Bunny",50000),
};
Sort(employees,Employee.CompareSalary);
//输出
}
五、多播委托
前面使用的委托都只包含一个方法的调用,但是委托也可以包含多个方法,这种委托叫做多播委托。使用多播委托就可以按照顺序调用多个方法,多播委托只能得到调用的最后一个方法的结果,一般我们把多播委托的返回类型声明为void。
Action action1 = Test1;
action2+=Test2;
action2-=Test1;
多播委托包含一个逐个调用的委托集合,如果通过委托调用的其中一个方法抛出异常,整个迭代就会停止。