2012-03-05 83 views
11

好的,我從基類A得到B類型。 A實現IDisposable明確的,但我必須做額外的清理工作在B,所以我實現BIDisposable在F#中調用一個基類顯式接口方法

interface IDisposable with 
    member i.Dispose() = 
     // ... additional work 
     base.Dispose() // <- want to do but cannot 

的問題是:如何從基地訪問的Dispose法?

(base :> IDisposable).Dispose() 

產生編譯器錯誤:Unexpected symbol ':>' in expression. Expected '.' or other token.

做這樣的事情

(i :> IDisposable).Dispose() 
當然

產生對運行時StackOverflowException - 我怎麼能做到這一點?對不起,但從未遇到過這樣的事情......

回答

8

你可能最好把你的清理邏輯放在一個虛擬方法中,並且只實現IDisposable一次。

type A() = 
    abstract Close : unit -> unit 
    default __.Close() = 
    printfn "Cleaning up A" 
    interface System.IDisposable with 
    member this.Dispose() = this.Close() 

type B() = 
    inherit A() 
    override __.Close() = 
    printfn "Cleaning up B" 
    base.Close() 

既然沒有protected訪問修飾符,您可以使用簽名文件,以使Close非公開(或標記它internal)。

base關鍵字只能用於成員訪問,而不能單獨使用。這就是爲什麼base :> IDisposable不起作用。

尋找反射器,Dispose只調用公衆Close方法。因此,您可以重新實施IDisposable並改爲撥打base.Close()

您可以在C#中使用相同的場景。實施IDisposable的可繼承類應該爲子類提供一種「插入」處理的方法。這通常通過提供從Dispose()調用的protected virtual Dispose(disposing)過載來完成。無論出於何種原因,DuplexClientBase不遵循此約定。考慮到Dispose僅轉發至Close,可能它被認爲是不必要的。

+0

行 - 我可能已經把這個錯誤的方式 - 一個不是我自己的類型(這是一個'DuplexClientBase')之一 - 所以這不是一個解。是的,我知道你不能以這種方式使用基地(編譯器說這麼多) - 問題是我如何得到基地處置。現在我解決了這個問題,通過使用公共成員方法來清理並通過調用此方法清理調用者+處理,但這只是一種破解,並且感覺錯誤 – Carsten 2012-03-05 15:57:17

+0

您是否檢查過'Dipose'是否有可重載超載? '保護虛擬無效Dispose(布爾處置)'是一種常見的模式。 – Daniel 2012-03-05 15:59:24

+0

我沒有檢查過,但沒有,如果MSDN是正確的:http://msdn.microsoft.com/en-us/library/ms576169.aspx - 我覺得你不能在F#中這樣做,如果有人可以證實這一點? – Carsten 2012-03-05 16:02:34

5

你不能從C#或任何語言做到這一點;顯式接口不允許這樣做。

+0

感謝您的反饋 - 事實上從未在此之前將它弄糟 - 但丹尼爾已經提到過,我只能標記一個答案,所以*只需在您的答案中使用+1 +1 – Carsten 2012-03-05 19:39:38

相關問題