在F#中调用基类显式接口方法

时间:2012-03-05 14:09:45

标签: inheritance f# explicit-interface

好的,我从基类B派生出一个A类型。 A明确实现IDisposable,但我必须在B中进行额外清理,因此我在IDisposable中实施B

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

问题是:如何从base访问Dispose-method?

(base :> IDisposable).Dispose()

产生编译器错误:Unexpected symbol ':>' in expression. Expected '.' or other token.

做类似

的事情
(i :> IDisposable).Dispose()

当然在运行时产生StackOverflowException - 所以我该怎么做呢?对不起,但从未遇到过类似的事情......

3 个答案:

答案 0 :(得分:9)

您可能最好将清理逻辑放在虚拟方法中并仅实施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的可继承类应该为子类提供一种方法来插入&#34;插入&#34;处置。这通常是通过提供从protected virtual Dispose(disposing)调用的Dispose()重载来完成的。无论出于何种原因,DuplexClientBase都不遵循此约定。鉴于Dispose只是转发到Close,可能认为没有必要。

答案 1 :(得分:5)

你不能用C#或任何语言做到这一点;显式接口不允许这样做。

答案 2 :(得分:0)

可以使用反射来调用基类显式接口。
请参阅我对C#相关问题的回答:
How to call an explicitly implemented interface-method on the base class