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> 类型来创建事件。
到目前为止,我们已经研究了一些把事件作为一等值的好处。最重要的概念可能是使用高阶函数处理事件的能力,视其为范围内序列的值。现在,我们将扩展前一章的动画示例,允许用户和动画进行交互。
分享到:
相关推荐
DevExpress_Components_Help_16.1.5_Downloadly.ir.rar
DevExpress v16.1.5 WinForms帮助文档(CHM)
DevExpress_Universal_Complete_16.1.5_Build_20160802_Downloadly.ir.rar```
DevExpress v16.1.5 WinForms Controls 帮助文档CHM 172M
DevExpress v16.1.5 ASP.NET Controls 帮助文档CHM 88M
优化:添加商品时可在当前选择的分类上进行添加 优化:进货记录、销售记录改为按日期降序排列 优化:对程序的运行性能和规范进行优化 优化 数据库多线程访问处理。 修复 新建帐本后未注销但实际已切换问题。 ...
devExpress帮助,pdf版本。
ADVANCED Codecs是一款适用于Windows 7/8/10/11等系统的万能影音解码器。软件轻巧简便,下载和安装的过程对电脑完全无负担,如果您看电影发生有声无影,或者是有影无声的情况,下载该解码器就可以解决了。...
9.3 在SqlDataSource控件中使用ASP.NET参数 271 9.3.1 使用ASP.NET参数对象 272 9.3.2 使用ASP.NET的Control-Parameter对象 274 9.3.3 使用ASP.NET的Cookie-Parameter对象 277 9.3.4 使用ASP.NET的Form-Parameter...
2.3 XAML中的属性和事件 26 2.3.1 简单属性与类型转换器 27 2.3.2 复杂属性 29 2.3.3 标记扩展 30 2.3.4 附加属性 31 2.3.5 嵌套元素 32 2.3.6 特殊字符与空白字符 35 2.3.7 事件 36 2.3.8 完整的Eight Ball示例程序...
2.3 XAML中的属性和事件 26 2.3.1 简单属性与类型转换器 27 2.3.2 复杂属性 29 2.3.3 标记扩展 30 2.3.4 附加属性 31 2.3.5 嵌套元素 32 2.3.6 特殊字符与空白字符 35 2.3.7 事件 36 2.3.8 完整的Eight Ball...
9.3.3 在顺序容器中添加元素 273 9.3.4 关系操作符 277 9.3.5 容器大小的操作 278 9.3.6 访问元素 279 9.3.7 删除元素 280 9.3.8 赋值与swap 282 9.4 vector容器的自增长 284 9.5 容器的选用 287 9.6 再谈string类型...
DevExpressComponents-16.1.6 包5
8.2. 在集合中出现的依赖对象 (Collections of dependent objects) 8.3. 组件作为Map的索引(Components as Map indices ) 8.4. 组件作为联合标识符(Components as composite identifiers) 8.5. 动态组件 ...
15.6.2 定义在接口中的内部接口 341 15.7 小结 342 第16章 多线程——Java中的并发协作 343 16.1 线程的基本知识 343 16.1.1 多线程编程的意义 343 16.1.2 定义自己的线程 344 16.1.3 创建线程对象 ...