当我使用F#时,我有一种奇怪的行为.当我在模块中使用let绑定时,如果值是从构造函数创建的,那么在外部使用时它是未初始化的.(我使用ModuleName.s2或ModuleName.f()从C#中使用它)
//in a module
let s1 = "1" //normal
let s2 = new String('i', 5) //null
let f () =
s2.Equals("something") //Exception
Run Code Online (Sandbox Code Playgroud)
这是正常行为吗?提前致谢.
编辑:为了调试,我选择将其编译为可执行文件.这可能是其他人指出的问题.
kvb*_*kvb 16
在F#库中,模块通过静态构造函数初始化,这些构造函数确保在使用任何模块的值之前进行初始化.相反,在F#可执行文件中,此初始化在应用程序的入口点中执行.这意味着如果另一个程序集引用F#应用程序(无论其他应用程序的语言是什么),都不会运行初始化代码.
UPDATE
Brian向我指出了规范的这一部分,这表明这是预期的行为.
看起来一种解决方法是提供一个明确的入口点,如下所示:
[<EntryPoint>]
let main _ =
0
Run Code Online (Sandbox Code Playgroud)
然后,您可以从C#app调用此main方法,以确保正确初始化模块的内容.
更新2
我误读了规范 - 你不需要实际调用引用程序集中的显式入口点.它的存在只会导致初始化正确发生.
出于某种原因,SomeModule.s2将其实现为(只读)属性,该属性返回unspeakable静态字段的值<StartupCode$FS>.$Program.s2@9.如果编译为应用程序,则在main方法中初始化该字段.从C#代码中使用时,不会调用此方法,因此不会初始化该字段.
如果编译为库,代码是相同的,除了字段在类的静态构造函数中初始化$Program,因此它在从C#使用时应该工作.
s1总是有效的原因是优化:F#编译器理解它是一个常量并实现f()为"1".Equals("something").
| 归档时间: |
|
| 查看次数: |
1237 次 |
| 最近记录: |