重载构造函数,无需初始化

Fra*_*ori 0 f#

我正在编写一个有两个构造函数的泛型类:第一个初始化每个字段,第二个(无参数)不应该初始化任何字段.

我发现实现此目的的唯一方法是使用"空"参数调用主构造函数,即Guid.Empty和null.除了没有看到我未经训练的眼睛的良好功能风格,这意味着我必须对a' : null第二个参数设置约束,我不想要:

type Container<'a when 'a : null>(id : Guid, content : 'a) =
    let mutable _id = id
    let mutable _content = content

    new() = Container<'a>(Guid.Empty, null)

    member this.Id
        with get() = _id
        and set(value) = _id <- value

    member this.Content
        with get() = _content
        and set(value) = _content <- value
Run Code Online (Sandbox Code Playgroud)

我看到两种解决方法:

  • 使用类似defaultc#关键字而不是null(F#中存在这样的东西?)
  • 使用不同的语法来指定构造函数和私有字段(如何?)

实现这个课程的最佳方法是什么?

kvb*_*kvb 5

F#模拟default是Unchecked.default<_>.也可以使用未初始化的显式字段:

type Container<'a>() =
    [<DefaultValue>]
    val mutable _id : Guid
    [<DefaultValue>]
    val mutable _content : 'a

    new (id, content) as this =
        new Container<'a>() then
        this._id <- id
        this._content <- content
Run Code Online (Sandbox Code Playgroud)

但是,总的来说,你的整体方法对于F#来说有点单一.通常,您使用简单的记录类型(可能使用静态方法来创建未初始化的容器,尽管这似乎有可疑的好处):

type 'a Container = { mutable id : Guid; mutable content : 'a } with
    static member CreateEmpty() = { id = Guid.Empty; content = Unchecked.defaultof<_> }
Run Code Online (Sandbox Code Playgroud)

在许多情况下,您甚至可以使用不可变记录类型,然后使用记录更新语句生成具有更新值的新记录:

type 'a Container = { id : Guid; content : 'a } 

[<GeneralizableValue>]
let emptyContainer<'a> : 'a Container = 
    { id = Guid.Empty; 
      content = Unchecked.defaultof<_> }

let someOtherContainer = { emptyContainer with content = 12 }
Run Code Online (Sandbox Code Playgroud)