Why can't Dispose(disposing) be overridden? - Forum - OpenEdge Development - Progress Community

Why can't Dispose(disposing) be overridden?

 Forum

Why can't Dispose(disposing) be overridden?

This question is answered

The Dispose(disposing) method is supposed to be overridable (non final), yet I get a compiler error when trying to override it in a derived Form or UserControl.

Overriding in c# works as expected.

What's going on here?

METHOD PROTECTED OVERRIDE VOID Dispose(disposing AS LOGICAL):

    SUPER:Dispose(disposing).

END METHOD.

-> Method 'Dispose' in class hierachy is FINAL. Cannot be overridden. (12999).

This is incorrect, the method is not final.

Verified Answer
  • Apparently this is documented (thank you Rob from tech support):

    https://documentation.progress.com/output/ua/OpenEdge_latest/#page/dvngp%2Foverriding-.net-methods.html%23

    You cannot override a .NET method defined as any of the following:
    *static
    *sealed (FINAL)
    *DestroyHandle( ) method
    *Dispose( ) method
    *Finalize( ) method
    *GetHashCode( ) method
    The listed methods are all defined as overrideable in .NET. However, ABL defines these methods as FINAL for an ABL session.
    Question still is: why?
    I want to extend the Dispose() method of my own derived control so I can clear extra allocated resources when the Dispose gets called by the .NET framework.
    Apparently this is not possible...
  • I looked into the history of the .NET bridge code and found that Dispose was made final because it is called on the garbage collection thread. Since the AVM isn't multi-threaded overriding Dispose in ABL often caused a crash. The other methods are probably forced to be final for similar reasons.

All Replies
  • It’s final in Progress.Windows.Form.
     
     

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • Even when inheriting from System.Windows.Forms.Form or UserControl it can't be overridden...

    And I don't think that's true Mike. It's overridden in Progress.Windows.Form, and that implies that it too is overridable afaik

  • But Progress.Windows.Form is a .NET class. So difference rules apply than with the ABL compiler. Just think about property overloading, …

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • You have to admit that that sounds a little strange right?

    Why should the Dispose() method be any different than any other protected non-final method?

    I know you can't override non abstract properties in ABL, that's a missing feature that's documented.

    But this...

  • Apparently this is documented (thank you Rob from tech support):

    https://documentation.progress.com/output/ua/OpenEdge_latest/#page/dvngp%2Foverriding-.net-methods.html%23

    You cannot override a .NET method defined as any of the following:
    *static
    *sealed (FINAL)
    *DestroyHandle( ) method
    *Dispose( ) method
    *Finalize( ) method
    *GetHashCode( ) method
    The listed methods are all defined as overrideable in .NET. However, ABL defines these methods as FINAL for an ABL session.
    Question still is: why?
    I want to extend the Dispose() method of my own derived control so I can clear extra allocated resources when the Dispose gets called by the .NET framework.
    Apparently this is not possible...
  • Trying to implement System.IDisposable:

    -> You are not allowed to define a class that implements System.IDisposable (14527)

    What is the rationale behind this?

  • What if you try to add a handler for Disposed event?

    Marian Edu

    Acorn IT 
    +40 740 036 212

  • Hi Marian, yes I thought of that as well, haven't tried it yet though...

    I'll have to investigate if the event gets published in time do to our housekeeping...

    Another option, which is less pleasing, is to override Dispose(disposing) in C# and call another protected method that I can then override in ABL...

    Either way, I would like to hear why Progress did this...

  • I looked into the history of the .NET bridge code and found that Dispose was made final because it is called on the garbage collection thread. Since the AVM isn't multi-threaded overriding Dispose in ABL often caused a crash. The other methods are probably forced to be final for similar reasons.

  • Ok Matt, so overriding Dispose(disposing) in c# and adding an extra virtual method to override in ABL is a bad idea in that case...

    I'm currently looking into subscribing the Disposed event like Marian suggested and that seems to work, for now...

    I assume the Disposed event handler is running in the main thread though.

  • Ah, I see that Matt found the answer.  Thanks Matt!  I remembered that we did explicitly make Dispose Final, but I couldn't remember why - only that we had a good reason!  Now I do remember that.  Yes, I do believe the event handler will run in the main thread.

    But again, please enlighten me as to what you're trying to accomplish with this.  I assume this is due to your memory leak issue.  Thanks.

  • Do you think we should add the reason for making these FINAL in the documentation?  Then you wouldn't have had to ask.

  • Hi Laura,

    Yes we're trying to track down a memory leak issue.

    We've had some ABL hybrid objects (Forms, ToolbarsManagers) sticking around, but even when explicitly disposing and/or deleting these, we didn't see the expected memory usage drop.

    Furthermore we see error 15580 (.NET is attempting to call a method in an ABL object that inherits from .NET. The object is either a form that has already been disposed or another object that has been explicitly deleted from the ABL. (15580).) in some cases pop up now, so we're probably going a bit too far...

  • So again- what do you intend to do in this Dispose handler that you think will help?  Because if you figure something out, we really need to know!  Thanks.

  • We implemented it using a handler normally to unhook event subscriptions that where added programmatically, but there are cases (I have not found the pattern yet)  where the application becomes unstable with object not initialized or object has been disposed errors.