15

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

pad
  • 41,040
  • 7
  • 92
  • 166
Random Dev
  • 51,810
  • 9
  • 92
  • 119

3 Answers3

10

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.

Daniel
  • 47,404
  • 11
  • 101
  • 179
  • 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 wrong – Random Dev Mar 05 '12 at 15:57
  • Have you checked if there's an overridable overload of `Dipose`? `protected virtual void Dispose(bool disposing)` is a common pattern. – Daniel Mar 05 '12 at 15:59
  • I have not checked explicit but not if MSDN is right: http://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? – Random Dev Mar 05 '12 at 16:02
  • oh - excelent idea - thank you. But still somewhat strange that you cannot to some of the simplest things in F# :( – Random Dev Mar 05 '12 at 16:32
  • 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! – Random Dev Mar 05 '12 at 16:48
  • You can't make it internal using either a signature file or access modifier if `B` isn't in the same assembly as `A`. – Rei Miyasaka Jul 04 '12 at 06:29
5

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

Brian
  • 117,631
  • 17
  • 236
  • 300
  • thank you for your feedback - indeed never stumpled upon this before - but Daniel already mentioned and I only can mark one answer so *just* +1 – Random Dev Mar 05 '12 at 19:39
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

Community
  • 1
  • 1
Roland Pihlakas
  • 4,246
  • 2
  • 43
  • 64
  • 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. – Random Dev Aug 21 '12 at 04:18