为什么我在 F# 中获取字符串的空值?

Why I'm getting null for a string in F#?

F# 上类型系统的好处之一是避免空异常……或者我相信这是……因为我遇到了空问题:

[<CLIMutable>]
type Customer = {
    [<AutoIncrement>] id:option<int64>
    code:string
    name:string
}

我是运行一个SQL代码:

let SqlFTS<'T>(table:string, searchTable:string, query:string) =
    use db = openDb()
    let sql = sprintf "SELECT * FROM %s WHERE id in (SELECT docid FROM  %s WHERE data MATCH %A)" table searchTable query
    printfn "%A" sql
    db.SqlList<'T>(sql) |> Seq.toArray

testCase "Customers" <| 
    fun _ -> 
        let rows = GenData.genCustomers(50)
        Customers.insert(rows)
        isEqual "Failed to insert" 50L (DB.SqlCount<Customers.Customer>())
        //Until here, it works
        let c = Customers.byId(1L)
        printfn "%A" c
        //Customers.byId return me a record with all the properties as NULLS!
        //Then c.name is null, and the code above fail.
        let rows = Customers.searchCustomers(c.name)

非常出乎意料。为什么我可以得到一条所有值为空的记录?

让我们从第 1 行开始:

[<CLIMutable>]

docs 为 CLIMutable 状态

Adding this attribute to a record type causes it to be compiled to a Common Language Infrastructure (CLI) representation with a default constructor with property getters and setters.

默认构造函数意味着字段将被初始化为默认值。字符串的默认值为空。这对 CLR 有效,对 C# 和 VB.NET 有效。您可能无法从 F# 调用默认构造函数,但几乎任何人都可以。

欢迎使用互操作;这可能会很痛苦。