gpt4 book ai didi

F# 元组常量从不初始化

转载 作者:行者123 更新时间:2023-12-04 11:48:27 25 4
gpt4 key购买 nike

我已经声明了一个这样的元组:

module MyModule =
let private INVALID_TUPLE = ("0", DateTime.MinValue)

当我在模块中引用它时,它始终为空:
let private invalidForNone someOtherTuple =
match someOtherTuple with
| None -> INVALID_TUPLE // it's null
| Some(t) -> t

此外,当我在元组声明上放置断点时,它永远不会命中。

如果我在脚本(fsx)文件中做同样的事情,开始调试,执行,元组声明上的断点命中并且对元组的引用很好。

我的模块的 ILSpy 显示生成的一些启动代码具有创建 INVALID_TUPLE 的 Main 方法。显然,由于某种原因,它没有运行?

这是一个重现该行为的示例(现在我意识到它与 MSTest 执行代码的方式有关)。从 C# 单元测试中调用它;结果将为空。事实上,F# 代码中根本不会执行断点。
module NullTupleTest
open System

let private INVALID_TUPLE = ("invalid", DateTime.MinValue)

let private TupleTest someTuple =
match someTuple with
| None -> INVALID_TUPLE
| Some(dt) -> dt

let Main = TupleTest None

最佳答案

当您以不运行 Main 的方式运行编译为可执行文件的代码时,可能会发生错误。编译后的可执行文件的方法 - 例如通过从库中引用它或使用单元测试运行程序。解决方案是将 F# 项目编译为库,并可能将另一个可执行文件作为入口点。 (或者,您也可以修改代码以避免 let 绑定(bind)全局值,但我更喜欢第一种方法。)

这是因为 F# 编译器对编译为可执行文件的代码和编译为库的代码处理初始化的方式不同。

  • 对于库,初始化代码放在静态构造函数中,在第一次访问字段时执行
  • 对于可执行文件,初始化代码放在 Main方法,它在应用程序启动时运行(但仅在它作为普通可执行文件启动时)。

  • 我认为这是因为 F# 编译器试图保持初始化发生的顺序(从上到下)。对于可执行文件,这可以通过在 Main 中运行初始化程序来完成。方法。对于库,没有可靠的方法来做到这一点(因为库没有“初始化”),因此使用静态构造函数是下一个最佳选择。

    关于F# 元组常量从不初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41367173/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com