我需要在一个模块中进行一些设置,我希望通过利用一个do块来完成.奇怪的是,我的do街区似乎永远不会受到打击.
更奇怪的是,如果我将模块代码加载到fsi中,它确实会受到攻击.这是我的例子:
Main.fs
[<EntryPoint>]
let main args =
printfn "%b" TestNamespace.M.x
0
Run Code Online (Sandbox Code Playgroud)
TestModule.fs
namespace TestNamespace
module M =
do
printfn "In do"
failwith "Error" // this is line 6
let x = true
Run Code Online (Sandbox Code Playgroud)
当我运行编译的可执行文件时,我得到
>test.exe
true
Run Code Online (Sandbox Code Playgroud)
为什么不抛出异常?如果我自己在FSI中运行模块,我会得到
In do
System.Exception: Error
at <StartupCode$FSI_0006>.$FSI_0006.main@() in C:\Projects\Personal2\Playground\fsscripts\fsscripts\TestModule.fs:line 6
Stopped due to error
Run Code Online (Sandbox Code Playgroud)
所以它得到了例外.
我在转换中看到do初始化程序被转换为单独的类
namespace \u003CStartupCode\u0024fsscripts\u003E
{
internal static class \u0024Library1
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
internal static int init\u0040;
static \u0024Library1()
{
ExtraTopLevelOperators.PrintFormatLine<Unit>((PrintfFormat<Unit, TextWriter, Unit, Unit>) new PrintfFormat<Unit, TextWriter, Unit, Unit, Unit>("In do"));
Operators.FailWith<Unit>("Error");
bool x = M.x;
}
}
}
Run Code Online (Sandbox Code Playgroud)
VS实际的模块代码:
namespace TestNamespace
{
[CompilationMapping(SourceConstructFlags.Module)]
public static class M
{
public static bool x
{
[DebuggerNonUserCode] get
{
return true;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
那么如何确保do块实际执行?
-
编辑,鉴于上面的示例计为一个简单的常量表达式,因此不会产生可观察的初始化,为什么以下也不起作用?
[<EntryPoint>]
let main args =
printfn "%d" (TestNamespace.M.x id 1)
0
Run Code Online (Sandbox Code Playgroud)
namespace TestNamespace
module M =
do
printfn "In do"
failwith "Error"
let x f a = f a
Run Code Online (Sandbox Code Playgroud)
这打印1没问题.
在重新阅读Tomas的注释之后进行编辑,因为函数被认为是一个常量表达式.
有关问题的详细解释,请参阅此前SO问题的答案.重要的一点说:
首次访问具有可观察初始化的值时,将执行该文件的静态初始化程序
现在,"可观察的初始化"有些棘手的想法,但简单的常量初始化肯定没有可观察的初始化 - 这就是为什么do不执行块的原因.您可以欺骗编译器认为存在一些必要的操作,例如通过添加do ():
module M =
do
printfn "In do"
failwith "Error" // this is line 6
let x = (do ()); true
Run Code Online (Sandbox Code Playgroud)