【问题标题】:call a base-class explicit interface method in F#在 F# 中调用基类显式接口方法
【发布时间】:2012-03-23 00:08:50
【问题描述】:

好的,我从基类 A 派生了一个类型 BA 实现 IDisposable 显式但我必须在 B 中进行额外的清理,所以我在 B 中实现 IDisposable

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

问题是:如何从 base 访问 Dispose 方法?

(base :> IDisposable).Dispose()

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

做类似的事情

(i :> IDisposable).Dispose()

当然会在运行时产生StackOverflowException - 那么我该怎么做呢?抱歉,以前从未遇到过这样的事情...

【问题讨论】:

    标签: inheritance f# explicit-interface


    【解决方案1】:

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

    【讨论】:

    • 在您的回答中,您正在使用反射。我没有明确这么说,但我真的不想要 hacky 方式 - 但谢谢。
    【解决方案2】:

    您不能使用 C# 或任何语言来执行此操作;显式接口不允许这样做。

    【讨论】:

    • 感谢您的反馈 - 确实以前从未偶然发现过这一点 - 但丹尼尔已经提到过,我只能标记一个答案,所以 只需 +1
    【解决方案3】:

    您最好将清理逻辑放在虚拟方法中并只实现一次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 :&gt; IDisposable 不起作用的原因。

    查看反射器,Dispose 只调用公共的Close 方法。所以你可以重新实现IDisposable 并改为调用base.Close()

    您可以在 C# 中使用相同的场景。实现IDisposable 的可继承类应该为子类“插入”处理提供一种方式。这通常通过提供从Dispose() 调用的protected virtual Dispose(disposing) 重载来完成。无论出于何种原因,DuplexClientBase 不遵循此约定。考虑到Dispose 只是转发到Close,也许它被认为是不必要的。

    【讨论】:

    • 好的 - 我可能用错了方式 - A 不是我自己的类型之一(它是 DuplexClientBase) - 所以这不是一个解决方案。是的,我知道你不能以这种方式使用 base(编译器说了这么多)——问题是我如何处理 base 的 Dispose。现在我通过使用公共成员方法进行清理来解决这个问题,并通过调用此方法 + dispose 来清理调用者,但这只是一个 hack,感觉很不对
    • 您是否检查过Dipose 是否存在可覆盖的重载? protected virtual void Dispose(bool disposing) 是一种常见的模式。
    • 我没有检查过,但如果 MSDN 是正确的,我没有检查:msdn.microsoft.com/en-us/library/ms576169.aspx - 我觉得你不能在 F# 中执行此操作,如果有人可以确认这一点吗?
    • 哦-好主意-谢谢。但是仍然有些奇怪,您无法使用 F# 中的一些最简单的东西 :(
    • 是的-确定您是对的(一直认为您可以在这种情况下在 C# 中使用 base,但不得不承认我从未尝试过)-您能否将其包含在您的答案中,以便我可以标记为答案?谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多