在F#中处理模式

时间:2017-01-14 16:20:35

标签: f# dispose

在F#中,继承不如在C#中常见,但这并不意味着它从未使用过。

如果我继承自在C#中实现IDisposable的类型,我通常会使用Dispose Pattern来抑制终结器。但是,我无法直接在F#中执行此操作,因为没有protected访问修饰符。

我已经在网上搜索了F#中Dispose Pattern的实现,但我只发现了Dispose()的天真解释。是否有一种模式可以让我在派生类中释放非托管资源,同时仍然会抑制性能优化的终结器?

为了使这个问题略显抽象,这里是一个典型的抽象基类型,我想继承:

[<AbstractClass>]
type ContentPage<'TViewModel, 'TView when 'TViewModel :> ReactiveViewModel and 'TViewModel : not struct>(theme: Theme) as this =
    inherit ContentPage()
    let messageReceived (message: AlertMessage) = this.DisplayAlert(message.Title, message.Message, message.Accept) |> ignore
    let mutable viewModel, listener = Unchecked.defaultof<'TViewModel>, Observable.Never<AlertMessage>().Subscribe(messageReceived)
    do base.BackgroundColor <- theme.Styles.BackgroundColor
    member __.ViewModel with get() = viewModel and set(value: 'TViewModel) = listener.Dispose(); viewModel <- value; listener <- value.MessageSent.Subscribe(messageReceived)
    abstract member CreateContent: unit -> View
    interface IViewFor<'TViewModel> with member __.ViewModel with get() = this.ViewModel and set(value) = this.ViewModel <- value
    interface IViewFor with member __.ViewModel with get() = (this :> IViewFor<'TViewModel>).ViewModel :> obj and set(value: obj) = (this :> IViewFor<'TViewModel>).ViewModel <- (value :?> 'TViewModel)
    interface IDisposable with member __.Dispose() = listener.Dispose()
    override __.OnAppearing() =
        base.OnAppearing()
        match box this.Content with
        | null -> this.Content <- this.CreateContent()
        | _ -> this |> ignore

如果我要实现C#Dispose模式的F#模拟,Dispose()会是什么样的?

1 个答案:

答案 0 :(得分:2)

您无法直接在f#中实现Dispose调用链。由于base.Dispose()的类型为base,因此ContentPage无效,IDisposable将不会被隐式投放到basetype BrokenPage() = inherit ContentPage() interface IDisposable with member __.Dispose() = (base :> IDisposable).Dispose() 仅允许成员访问,因此您也无法显式转换它。以下内容无法编译。

protected

要解决这个问题需要另一种方法。由于F#中没有type ContentPage() = abstract Close : unit -> unit default this.Close() = // cleanup ContentPage here GC.SuppressFinalize(this) interface IDisposable with member this.Dispose() = this.Close() type SomePage() = inherit ContentPage() override this.Close() = // cleanup SomePage here base.Close() interface IDisposable with member this.Dispose() = this.Close() ,所以这个成语仍然不完美。

params[:session][:test_password]