2017-01-14 6 views
1

F#では、継承はC#よりも一般的ではありませんが、使用されることはありません。F#でのパターンの破棄

C#でIDisposableを実装する型から継承している場合、通常はファイナライザを抑制するためにDispose Patternを使用します。しかし、protectedアクセス修飾子がないので、私はF#でこれを直接行うことはできません。

私はF#でDispose Patternの実装をオンラインで検索しましたが、私はDispose()の単純な解釈しか見つけられませんでした。パフォーマンスの最適化のためにファイナライザを抑制したまま、派生クラスでアンマネージリソースを解放できるパターンはありますか?

この質問はわずかに少ない抽象ようにするには、ここで私は継承したい典型的な抽象基本型である: Dispose()私はC#2のF#のアナログを実装した場合にどのように見えるか

[<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 

パターンを処分する?

+1

「保護された」は、そのイディオムの最も重要な側面です。代わりにそれを公開し、より重要なことに乗ります。 ; - ]あなたのタイプがファイナライザを持っていればファイナライズを抑止し、ContentPageはそうではないので、それはやりとりポイントのようなものです... – ildjarn

+0

それは確かに仕事をするでしょう。 :) –

+0

ファイナライザについての公平な点ですが、これは抽象基本クラスであり、派生したクラスで何をするかを制御できません。 –

答えて

1

Disposeコールチェーンをf#で直接実装することはできません。 はContentPageタイプであり、暗黙的にIDisposableにキャストされないため、base.Dispose()は機能しません。 baseはメンバーへのアクセスのみを許可するので、明示的にキャストできません。以下はコンパイルされません。

type BrokenPage() = 
    inherit ContentPage() 

    interface IDisposable with 
     member __.Dispose() = 
      (base :> IDisposable).Dispose() 

これを回避するには、別の方法が必要です。 F#にはprotectedが存在しないため、イディオムはまだ完璧ではありません。

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() 
関連する問題