2017-10-13 49 views
3

我正在研究用F#编写的WebApi项目。下面的代码段:F#Guid.Parse TypeInitializationException

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时都会创建一个新实例...

+0

“list”和“list.Get”是什么类型? – scrwtp

+1

“TypeInitializationException”的文字是什么?它的'InnerException'? –

+0

不管是什么'list'和'list.Get',在这一点上'MyGuid'已经是'错误'了。 看不到Innerexceptions,只有''MyGuid'抛出了'System.TypeInitializationException'类型的异常' – Emaborsa

回答

2

我不是100%确定这是这里的问题,但我看过在使用单元测试运行器时有时会出现类似的行为我的猜测是,错误发生的原因是顶级MyGuid变量未正确初始化,并且具有默认零值(因此查找失败)。

在F#中初始化全局变量的方式非常棘手 - 如果将代码编译为可执行文件,这可能发生在Main方法中。但是,如果将代码编译为库,编译器会将初始化检查插入到库中类型的静态构造函数中(以确保在访问任何内容之前所有内容都已初始化)。

我认为如果您将代码编译为可执行文件,然后将其作为库加载 - 入口点未被调用,并且变量未初始化,则可能会中断。我不确定WebApi究竟是如何加载库,但这可能是一个问题 - 尤其是如果您将F#代码编译为可执行文件。

将全局变量转换为函数的解决方法解决了这个问题,因为该函数被编译为一个方法,因此您可以避免引用未初始化的值。可悲的是,我认为没有更好的解决方法。

+0

如前所述,通过调用'list.Get'不是查找问题。通过在这一行设置一个断点,Guid内部有这个TypeInitializationException,而不是Guid实例。我正在开发一个web项目'WebApi',在这一点上我认为它是一种错误。 – Emaborsa

+0

@Emaborsa我看到这被标记为答案 - 这背后的问题是什么?我的猜测是否接近,还是其他的? –

+0

我不知道是什么问题。我将静态变量转换为函数。如果在一个更大的项目中,我会创建一个单例模块/类,以避免同一个GUID的多个实例。 – Emaborsa

相关问题