思考并回答以下问题:
- 多播委托的返回值是什么样的?
- 调用带引用参数的委托是什么样的?
*
本章涵盖:
调用带返回值的委托
如果委托有返回值并且在调用列表中有一个以上的方法,会发生下面的情况。
- 调用列表中最后一个方法返回的值就是委托调用返回的值。
- 调用列表中所有其他方法的返回值都会被忽略。
例如,如下代码声明了返回int值的委托。Main创建了委托对象并增加了另外两个方法。然后,它在WriteLine语句中调用委托并打印了它的返回值。图10演示了代码的图形表示。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36using System;
using System.Collections.Generic;
namespace Test
{
delegate int MyDel(); // 声明有返回值的方法
class MyClass
{
int IntValue = 5;
public int Add2()
{
IntValue += 2;
return IntValue;
}
public int Add3()
{
IntValue += 3;
return IntValue;
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
MyDel mDel = mc.Add2; // 创建并初始化委托
mDel += mc.Add3; // 增加方法
mDel += mc.Add2; // 增加方法
Console.WriteLine("Value:{0}", mDel()); // 调用委托并使用返回值
Console.ReadKey();
}
}
}
这段代码产生了如下的输出:1
value:12
图10 最后一个方法执行的返回值是委托返回的值
调用带引用参数的委托
如果委托有引用参数,参数值会根据调用列表中的一个或多个方法的返回值而改变。
- 在调用委托列表中的下一个方法时,参数的新值(不是初始值)会传给下一个方法。
例如,如下代码调用了具有引用参数的委托。图11演示了这段代码。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34using System;
using System.Collections.Generic;
namespace Test
{
delegate void MyDel(ref int x);
class MyClass
{
public void Add2(ref int x)
{
x += 2;
}
public void Add3(ref int x)
{
x += 3;
}
static void Main()
{
MyClass mc = new MyClass();
MyDel mDel = mc.Add2; // 创建并初始化委托
mDel += mc.Add3; // 增加方法
mDel += mc.Add2; // 增加方法
int x = 20;
mDel(ref x);
Console.WriteLine("Value:{0}", x); // 调用委托
Console.ReadKey();
}
}
}
这段代码产生了如下的输出:1
value:12
图11 引用参数的值会在调用间发生改变
自己的理解和总结
学习委托一定要明确使用场景。设计模式也是。为了解决什么问题而使用委托。
这边举个例子。写日志问题。日志从一处产生。产生之后可以有很多种处理。比如写进数据库,比如发送邮件,比如直接展示。
没有委托之前,如果需要增加一个日志处理,则需要在日志产生的代码处改动增加代码。
有委托后,只需要在日志产生的地方直接调用委托就OK了。想再增加处理方式可以在外面扩展。写好一个方法后再追加进委托即可。
目的就是为了解耦合,对修改关闭,对扩展开放。
事件是对委托的进一步封装,增强了委托的安全性,实现了发布/订阅。