我写了一个非常好的fsi脚本,想要编译它以便我可以更轻松地移动它。但是,当我编译它时,FileHelpers突然开始出错。
以下代码使用FileHelpers 2.9.9。这是一个简单的工作示例来说明问题,test.fsx
:
#r "FileHelpers.dll"
open FileHelpers
[<DelimitedRecord(",")>]
type Type =
val field1 : string
val field2 : int
override x.ToString() = sprintf "%s: %d" x.field1 x.field2
let readFile<'a> file = seq {
use engine1 = new FileHelperAsyncEngine(typeof<'a>)
use tmp1 = engine1.BeginReadFile(file)
engine1.ReadNext() |> ignore
while engine1.LastRecord <> null do
yield engine1.LastRecord :?> 'a
engine1.ReadNext() |> ignore
}
readFile<Type> "test.csv" |> Seq.iter (printfn "%A")
将文件test.csv
设为
test1,1
test2,2
test3,3
如果我将代码作为fsi .\test.fsx
运行,它将正常工作。但是,如果我尝试使用fsc .\test.fsx
进行编译并运行.\test.exe
,则会收到错误Unhandled Exception: FileHelpers.BadUsageException: The record class Type needs a constructor with no args (public or private)
。在脚本和编译模式下工作的解决方法是
[<DelimitedRecord(",")>]
type Type () =
[<DefaultValue>]
val mutable field1 : string
[<DefaultValue>]
val mutable field2 : int
override x.ToString() = sprintf "%s: %d" x.field1 x.field2
为什么它可以作为脚本运行但不编译?如果可能的话,我想保持不变。感谢您的任何见解!
答案 0 :(得分:1)
FSI使用System.Reflection.Emit即时编译您的F#代码。看来,使用System.Reflection.Emit生成的类型总是至少有一个构造函数(默认的公共构造函数或显式定义的构造函数)。因此,FSI发出的代码不可能完全模仿编译代码的结果,编译代码根本没有构造函数(既不公开也不私有)。