一、什么是委托
1.1官方解释
委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。
1.2个人理解
委托就是执行方法(函数)的一个类。
事件是一种特殊的委托。
二、如何申明委托
2.1 delegate
public delegate int TestDelegate(int x, int y);
2.2 Action
Action是无返回值的泛型委托。
Action 表示无参,无返回值的委托
Action<int,string> 表示有传入参数int,string无返回值的委托
2.3 Func
Func是有返回值的泛型委托
Func 表示无参,返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
2.5 四者之间的区别
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型
Action至少1个参数,至多4个参数,无返回值,
Func至少0个参数,至多4个参数,根据返回值泛型返回。必须有返回值,不可void
三、如何使用委托
3.1 Labmda表达式
TestDelegate d2= (string name) => { Console.WriteLine("你好,{0}!", name); };
d2("Terry");
3.2匿名方法
delegate void TestDelegate(string myName);
TestDelegate d2 = delegate(string name)
{
Console.WriteLine("Hello,{0}!", name);
};
d2(“Test”);
3.3 函数申明
private void DelegateMethod(string name)
{
Console.WriteLine("Hello,{0}!", name);
}
TestDelegate d2 = new TestDelegate(DelegateMethod);
d2(“Test”);
四、使用委托有哪些特点
委托类似于 C++ 函数指针,但它们是类型安全的。
委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以链接在一起;例如,可以对一个事件调用多个方法。
方法不必与委托签名完全匹配。
五、委托使用场景
委托一般都使用在 Observer模式(观察者模式)。
Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。
Observer模式主要包括如下两类对象:
被监视对象:往往包含着其他对象所感兴趣的内容。
监视者:当对象中的某件事发生的时候,会告知建设者,而建设者则会采取相应的行动。
例如:当你程序处理大批量数据时,需要在程序界面显示进度条进行友好提示,这时你通过委托来实现相当方便。
个人学习笔记:
class Program
{
static void Main(string[] args)
{
}
//---------------------------------------------------------------------------------------
//普通委托
private delegate void getStr(string x);//定义委托就是定义一个新的类
private static void deleTest()
{
getStr k = new getStr(test_1);
k("123434"); //k("aaa")与k.Invoke("aaa")完全相等
k.Invoke("wewqrwer");
}
private static void test_1(string s)
{
Console.WriteLine(s);
}
//---------------------------------------------------------------------------------------
//Func委托 Func<T,T,返回值>
private static void FuncTest()
{
Func<double, double>[] k = { M.M1, M.M2 };
for (int i = 0; i < k.Length; i++)
{
test_2(k[i], 12);
}
}
private static void test_2(Func<double, double> action, double value)
{
double result = action(value);
Console.WriteLine(result);
}
//---------------------------------------------------------------------------------------
//Action委托 Action<T,T>
private static void ActionTest()
{
Action<double>[] k = { M.M3, M.M4 };
for (int i = 0; i < k.Length; i++)
{
test_3(k[i], 12);
}
}
//多播委托,可识别+,=,+=,-=运算符
private static void Action_1()
{
Action<double> k = M.M3;
k += M.M4;
//test_3(k, 10); 直接调用多播委托方法,如抛出异常将会停止迭代,应写入迭代方法
Delegate[] dele = k.GetInvocationList(); //返回多播委托数组
foreach(Action d in dele)
{
try { d(); } catch{ }
}
}
private static void test_3(Action<double> action, double value)
{
action(value);
}
//---------------------------------------------------------------------------------------
//匿名方法用作委托参数,C#3.0开始,可使用lambda替代匿名方法
private static void test_4()
{
double v = 50;
Action<double> ac = delegate (double value)
{
value = value * 2 * v;
Console.WriteLine(value);
};
ac(10);
}
//---------------------------------------------------------------------------------------
//lambda 表达式替换匿名方法
private static void test_5()
{
double v = 50;
Action<double> ac = value =>
{
value = value * 2 * v;
Console.WriteLine(value);
};
ac.Invoke(10);
}
}
class M {
public static double M1(double value) => value * 2;
public static double M2(double value) => value * value;
public static void M3(double value)
{
Console.WriteLine(value * 2);
}
public static void M4(double value)
{
Console.WriteLine(value * value);
}
}