委托

思考并回答以下问题:

  • 多播委托的返回值是什么样的?
  • 调用带引用参数的委托是什么样的?
    *

本章涵盖:

调用带返回值的委托

如果委托有返回值并且在调用列表中有一个以上的方法,会发生下面的情况。

  • 调用列表中最后一个方法返回的值就是委托调用返回的值。
  • 调用列表中所有其他方法的返回值都会被忽略。

例如,如下代码声明了返回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
36
using 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
34
using 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了。想再增加处理方式可以在外面扩展。写好一个方法后再追加进委托即可。

目的就是为了解耦合,对修改关闭,对扩展开放。

事件是对委托的进一步封装,增强了委托的安全性,实现了发布/订阅。

0%