我正在用F#编写WebApi项目。这是一个片段:
module MyModule
open System
let MyGuid = Guid.Parse "934F0B12-D00A-491D-862D-EE745EF3C560"
let myFunction list =
list.Get(MyGuid) // --> here MyGuid has the TypeInitializationException before list.Get is called
通过调试,我可以看到MyGuid实际上有一个错误
更改以下代码,它可以工作:
module MyModule
open System
let MyGuid () = Guid.Parse "934F0B12-D00A-491D-862D-EE745EF3C560"
let myFunction list =
list.Get(MyGuid())
我实际上知道第一个示例的MyGuid是变量,第二个示例是函数定义,但是为什么第一个会引发异常?我的代码MyGuid使用了几次。因此,在第一个示例中,我只有一个实例,在第二个示例中,每次调用MyGuid时都有一个新实例...
最佳答案
我不是100%肯定这是问题所在,但是有时使用单元测试运行程序时,我已经看到类似的行为。我的猜测是发生此错误是因为顶级MyGuid
变量未正确初始化且具有默认的零值(因此,查找失败)。
在F#中初始化全局变量的方式很棘手-如果将代码编译为可执行文件,则可能会从Main
方法中发生。但是,如果您将代码作为库进行编译,则编译器会将初始化检查插入到库中类型的静态构造函数中(以确保在访问任何内容之前,所有内容都已初始化)。
我认为,如果将代码编译为可执行文件,然后将其作为库加载,则可能会中断-不会调用入口点,因此不会初始化变量。我不确定WebApi加载库的精确程度,但这可能是一个问题-特别是如果将F#代码编译为可执行文件。
将全局变量转换为函数的解决方法可以解决此问题,因为函数是作为一种方法编译的,因此避免引用未初始化的值。可悲的是,我认为没有更好的解决方法。