16.1.5 在 F# 中声明事件

16.1.5 在 F# 中声明事件

为了声明一个新事件,需要两件东西。首先,必须创建一个可以发布的事件值,以便其他斯可以订阅新创建的事件。这一次,我们需要使用 F# 特有的 IEvent <'T> 接口,而不是 .NET 的 IObservable<'T>。我们还需要一种触发该事件的方法。在 C# 中,可以使用方法调用的语法,来触发事件,只是从声明的类中。当我们在 F# 中创建一个新的事件时,就会得到触发它的函数。

所有这一切,用示例来说明,就更清晰了。清单 16.6 显示了一个简单的具体对象类型(类),只公开一个事件和有时触发事件的一个方法。

Listing 16.6 Declaring an event as a class member (F# Interactive)

> type Counter() =
let mutable num = 0
let changedEvt = new Event<_>()

member x.SignChanged = changedEvt.Publish
member x.Add(n) =
let original = num
num <- num + n
if (sign(original) <> sign(num)) then
changedEvt.Trigger(num);;

> let c = Counter()
c.SignChanged |> Observable.add (printfn "Number: %d");;
type Counter = (...)

> c.Add(10);;
Number: 10

> c.Add(10);;
> c.Add(-30);;
Number: –10

Counter 类包含一个存储当前数值的可变字段,Add 方法修改这个字段,当存储数值变化时,应该触发 SignChanged 事件。为了声明一个新的事件,我们使用来自 F# 库的 Event<'T> 类。此类包含 Publish 成员,返回相应的、可以监听的 IEvent<'T> 值,和运行这个事件的 Trigger 成员。

清单 16.6 显示在类型声明中处理事件的典型方式。将Event 类的实例存储为本地值 ,公开由 Publish 成员返回的事件值,作为该类的公共成员,以便用户可以监听这个事件,但不能触发它。当满足适当条件时,使用 Trigger 成员,触发该事件。

声明兼容 C# 的事件

我们在这一节中使用的、创建事件的技术可以很自然地用于 F#,但不能显示为标准的 C# 事件。F# 编译器不会以任何特殊的方式,对待 IEvent<'T> 类型的属性,因此,它将 SignChanged 编译为一个标准属性的成员。我们可以在 C# 中使用接口的 AddHandler 方法的,但这会引起混乱。

幸运的是,F# 编译器提供了一种简单的方法解决此问题。如果要在 F# 中声明一个标准的 .NET 事件,可以使用 CLIEvent 属性值。编译器能够理解这个属性值,在这里,编译器将创建一个事件,可以使用 C# 中的 += 运算符和-= 运算符进行访问:

type Counter() =
[<CLIEvent>]
member x.SignChanged = ev.Publish

到目前为止,F# 我们创建的事件和常用的 C# 事件的另一个区别,是 F# 使用它自己的泛型委托类型(Handler<T>)。如果要使用某些其他委托时,可以用 Event<'TDel, 'T> 类创建事件,它用第一个参数值来指定委托的类型。例如,在典型的 Windows 编程中,可以使用 Event<EventHandler,EventArgs> 类型来创建事件。

到目前为止,我们已经研究了一些把事件作为一等值的好处。最重要的概念可能是使用高阶函数处理事件的能力,视其为范围内序列的值。现在,我们将扩展前一章的动画示例,允许用户和动画进行交互。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值