call a base-class explicit interface method in F#
Asked Answered
G

3

16

Ok I derive a type B from a base class A. A implements IDisposable explicit but I have to do additional cleanup in B, so I implement IDisposable in B:

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

Question is: how to access the Dispose-method from base?

(base :> IDisposable).Dispose()

yields compiler error: Unexpected symbol ':>' in expression. Expected '.' or other token.

Doing something like

(i :> IDisposable).Dispose()

of course yields a StackOverflowException on runtime - so how can I do this? Sorry but never encountered something like this before...

Gonorrhea answered 5/3, 2012 at 14:9 Comment(0)
G
11

You're probably better off putting your clean-up logic in a virtual method and implementing IDisposable only once.

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()

Since there's no protected access modifier, you can use a signature file to make Close non-public (or mark it internal).

The base keyword can only be used for member access, not standalone. That's why base :> IDisposable doesn't work.

Looking in Reflector, Dispose only calls the public Close method. So you could re-implement IDisposable and call base.Close() instead.

You could have this same scenario in C#. Inheritable classes that implement IDisposable should provide a way for subclasses to "plug in" to disposal. This is usually done by providing a protected virtual Dispose(disposing) overload that's called from Dispose(). For whatever reason, DuplexClientBase doesn't follow this convention. Perhaps it was deemed unnecessary given that Dispose merely forwards to Close.

Geerts answered 5/3, 2012 at 15:10 Comment(6)
ok - I might have put this the wrong way - A is not one of my own types (it's a DuplexClientBase) - so this is not a solution. And yes I know that you cannot use base this way (the compiler says so much) - the question is HOW do I get to the Dispose of base. For now I solved this by using a public member method to clean up and have the callers clean up by calling this method + dispose but this is only a hack and feels just wrongGonorrhea
Have you checked if there's an overridable overload of Dipose? protected virtual void Dispose(bool disposing) is a common pattern.Geerts
I have not checked explicit but not if MSDN is right: msdn.microsoft.com/en-us/library/ms576169.aspx - I get the feeling that you cannot do this in F# if so can someone confirm this?Gonorrhea
oh - excelent idea - thank you. But still somewhat strange that you cannot to some of the simplest things in F# :(Gonorrhea
yeah - sure you are right (had always thought you coude use base in C# in such a case but have to admit I never tried) - can you include this into your answer so I can mark is as the answer? Thank you!Gonorrhea
You can't make it internal using either a signature file or access modifier if B isn't in the same assembly as A.Woollyheaded
L
5

You can't do this from C# or any language; explicit interfaces do not allow this.

Laddy answered 5/3, 2012 at 19:17 Comment(1)
thank you for your feedback - indeed never stumpled upon this before - but Daniel already mentioned and I only can mark one answer so just +1Gonorrhea
H
0

Calling base class explicit interface can be done using reflection.
See my answer to a related question about C#:
How to call an explicitly implemented interface-method on the base class

Housemother answered 20/8, 2012 at 19:44 Comment(1)
in your answer there you are using reflection. I did not explicitly say so but I don't really want the hacky way - but thank you.Gonorrhea

© 2022 - 2024 — McMap. All rights reserved.