一.委托的概念
1)什么是委托
之间学过的任何类型,不管是值类型还是引用类型,其变量都可以进行赋值,或者作为方法的参数进行传递,而如何引用方法或者把方法作为参数进行传递呢?这就需要用到委托 delegate.
委托也是一种类型,它与类一样,需要我们自己来定义。
委托的定义如下: delegate 返回值类型 委托类型名 (参数)
例如:delegate void GreetDelegate(string name);
定义时委托类型的返回值和参数与要引用的方法的的放回值和参数一致,二者在外形上一样,只是委托用delegate修饰。
2)如何使用委托
委托的使用分以下三步:
1.委托的声明;
2.委托的实例化;
3.委托的调用;
委托类似与函数指针,但与函数指针不同的是,委托是面向对象的、类型安全的和保险的。委托既能引用静态变量,也能引用实例方法。
3)委托实例
class MainClass
{
public delegate void GreetingDelegate(string name); //声明一个委托
public static void Main(string[] args)
{
//声明委托变量
GreetingDelegate greetingDelegate;
//实例化委托
greetingDelegate = Myname; //只是赋值方法名
//委托的调用
greetingDelegate("xingjiashi");
}
public static void Myname(string name)
{
Console.WriteLine("My name is {0}", name);
}
}
例子:创建委托来绑定打印数组(泛型)的方法
using System;
namespace DelegateStu
{
//创建一个泛型方法1
public class Myclass<T>
{
//定义一个委托
public delegate int CompareDelegate(T a, T b);
//在Sort方法中调用类委托compare
public static void Sort(T[] arr,CompareDelegate compare)
{
for (int i = 0; i < arr.Length-1;i++)
{
for (int j = 0; j < arr.Length - 1 - i;j++)
{
if(compare(arr[j],arr[j+1])>0)
{
T temp = arr[j+1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
public Myclass()
{
}
}
}
public static void Main(string[] args)
{
string[] names = new string[] { "han", "jia", "tong", "piao", "fang" };
Myclass<string>.Sort(names, StrCompare); //这里实现了委托的实例
}
//Compare
public static int StrCompare(string a, string b)
{
return a.CompareTo(b);
}
4)理解委托
委托是一个类,它定义了方法的类型,使得可以将方法当做另一方法的参数来进行传递,也即是方法的参数是一个委托变量,在调用此方法时,就可以把一个方法作为参数传递给委托变量;
5)合并委托
委托对象的一个有用属性是:可以使用 + 运算符将多个对象分配给一个委托实例。多播委托包含已分配委托的列表在调用多播委托时,它会按顺序调用列表中的委托。
注意:只能合并相同类型的委托。
第一种方式: 第二种方式:
Greeting greet; Greeting greet,greet_1,greet_2;
greet=ChineseGreet; greet_1=EnglishGreet
greet+=EnglishGreet; greet_2=ChineseGreet ;
greet("涵") greet=greet_1+greet_2;
greet("涵");
注意:当委托绑定多个有返回值的方法时,其结果是最后绑定的那个方法的返回值,前面的绑定的返回值会被最后绑定方法的返回值所覆盖,所以使用委托时一般不带返回值。
总结:
(一). 委托和引用方法必须保持一致:
1.参数个数、类型、顺序必须完全一致。
2.返回值必须一致。
(二). 一个委托被同时映射到静态方法和实例方法,并分别返回特定的信息。
二 . 匿名委托 其他四种形式的委托
1)delegate 定义的匿名委托
2)lambda表达式
3)Func委托
4)Action委托
委托变量在绑定方法时,是把方法名赋值给委托变量名,这样就需要在类里面定义方法,而有些方法只用到了一次,这样的方法在类里面过多时,程序的可读性就不太好,针对这种情况,可以使用匿名委托,即不用在类里面额外定义方法。
1.delegate定义的匿名委托
格式:delegate(参数){要执行的代码};
参数:相当于绑定方法的参数
{}; 里面相当于绑定方法的方法体
由于是赋值,是一个语句,后面的 ; 不要省略
using System;
namespace LearningSummary
{
class MainClass
{
delegate void Dele(string a, string b);
public static void Main(string[] args)
{
Dele s = delegate (string arg1, string arg2)
{
Console.WriteLine(arg1 + arg2);
};
s += delegate (string a, string b)
{
Console.WriteLine("delegate 匿名委托");
};
s("春", "夏");
}
}
}
2.lambda表达式
格式:(参数)=>{要执行的代码};
参数:相当于绑定方法的参数
{}; 里面相当于绑定方法的方法体
由于是赋值,是一个语句,后面的 ; 不要省略
using System;
namespace LearningSummary
{
class MainClass
{
public delegate bool EqualDelegate(string a, string b);
public static void Main(string[] args)
{
EqualDelegate equaldelegate = (string str_1, string str_2) =>
{
return str_1 == str_2;
};
}
}
}
3.Func委托
格式:
Func<int,int,int> s=delegate(int,int){
return int;
};
使用Func泛型,前面两个是参数类型,最后一个是返回值,其变量可以绑定匿名委托方法,lambda表达式和相同类型的方法,此种委托一定会有返回值;
Func<string, string, int> s = delegate (string arg1, string arg2)
{
return arg1.CompareTo(arg2);
};
4.Action委托
格式:
Action<string> action=delegate(string){
};
使用Action泛型,<>里面的类型是参数的类型,该种委托可以绑定匿名委托,lambda表达式和方法,但其一定没有返回值。
Action<string, string> s_2 = delegate (string arg1, string arg2)
{
//return arg1.CompareTo(arg2);
Console.WriteLine(arg2+arg1);
};