C#的委托与事件搭配,即是观察者模式的一种实现。

因为观察者模式的原理很易懂,不作多讲,本文纯粹用于记录语法。

# delegate(委托)

```csharp
//声明没有参数,没有返回值的委托类型XXXX
public delegate void XXXX();
```
声明一个委托类型(类似typedef XXXX C++/C的函数类型)

> 注:不是产生一个对象。

然后利用声明出来的委托类型,我们可以利用它的对象,赋予其对应类型的函数。
从而实现出类似调用函数指针的效果。

```csharp
//委托类型XXXX的对象
public XXXX delegateObj1;

public void func1(){}
public void func2(){}
public void func3(int a){}

//可将某个同样类型的函数赋给该对象
delegateObj1 = func1;

//调用委托对象等同于调用它代表的函数
delegateObj1();//等价于func1();

delegateObj1 = func2;
delegateObj1();//等价于func2();

delegateObj1 = func3;//类型不匹配,语法错误
```

# event(事件)

单纯用委托的话只能一对一调用(一次调用,一个函数触发)。

而通过利用事件机制,我们可以实现一对多的调用(一次调用,多个相关事件(函数)触发)。

而且它添加/移除委托对象(相当于观察者模式里的观察者)的操作十分方便,使用+=或-=即可。

```csharp
//先声明一个委托类型
public delegate void XXXX();
//委托事件对象
public event XXXX EventObj1;//此处比一般委托多了个event
```

```csharp
EventObj1 += func1; //添加
EventObj1 += func2; //添加

EventObj1(); //调用func1(),func2()

EventObj1 -= func1; //移除
EventObj1(); //调用func2()
```

# Action/Func

Action/Func主要是为了简化委托(delegate)语法,它们本质都是委托。

```csharp
//无返还值,不带参数的委托对象
public delegate void XXXX();
public XXXX obj1;
```
在上面我们看到委托语法,必须为委托类型命名(声明委托),才能使用该委托类型。

但是使用Action/Func可以无需声明委托类型的语句,直接利用Action<...>/Func<...>来用自己想要的委托类型。
> Action和Func的源码底层实际也是delegate的封装

- Action<...>用于无返还值的委托类型
- Func<...,T>用于有返回值的委托类型,最后一个类型参数 T 代表返还值类型。

 

```csharp
//无返还值,不带参数的委托对象
public Action obj3;
//无返还值,带int参数的委托对象
public Action<int> obj4;

//double返还值,无参数的委托对象
public Func<double> obj5;
//int返还值,带string,double参数的委托对象
public Func<string,double,int> obj6;

//将Action应用至事件
public event Action<int> EventObj1;
EventObj1 += obj4;
EventObj1 += func1;
EventObj1 += func2;
EventObj1();//调用obj4(),func1(),func2()
```

 

# Lambda表达式

Lambda表达式是用于简便快速写简单函数的语法,而且这些函数往往要用于委托对象。

Lambda表达式基本形式:
```csharp
(参数...) => { 函数内容... }
```

> 参数在它的类型可自动推导的情况下,才可以省略参数类型。如果谨慎起见,可以不省略,从而避免隐式类型转换。

```csharp
Action obj1;
obj1 = () => { Debug.Log("FGNB"); };

Action<int> obj2;
obj2 = (int x) => { Debug.Log(x); };
obj2 = (x) => { Debug.Log(x+233); };//也可以省略参数类型

Func<int,int> obj3 = (int x) => { return x; };

```

# 小结
- 大部分情况下可使用Action/Func而不是直接使用delegate
- 要观察者模式,应使用event和委托(Action/Func/delegate)搭配。更加完善的做法是再搭配Dictionary,通过Key找到想要的事件委托对象,然后可以添加/移除/通知该对象的观察者。
- Lambda表达式适用于快速编写简短的函数,复杂的应该做成类方法方便调试。

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!