Why can't Dispose(disposing) be overridden?

Posted by Lieven De Foor on 04-Jul-2018 08:17

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.

Posted by Lieven De Foor on 04-Jul-2018 09:32

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

Posted by Matt Gilarde on 05-Jul-2018 07:32

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

Posted by Mike Fechner on 04-Jul-2018 08:38

It’s final in Progress.Windows.Form.
 
 

Posted by Lieven De Foor on 04-Jul-2018 08:42

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

Posted by Mike Fechner on 04-Jul-2018 08:46

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

Posted by Lieven De Foor on 04-Jul-2018 09:23

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

Posted by Lieven De Foor on 04-Jul-2018 09:32

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

Posted by Lieven De Foor on 04-Jul-2018 09:44

Trying to implement System.IDisposable:

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

What is the rationale behind this?

Posted by marian.edu on 04-Jul-2018 09:54

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


Marian Edu

Acorn IT 
+40 740 036 212

Posted by Lieven De Foor on 04-Jul-2018 09:59

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

Posted by Matt Gilarde on 05-Jul-2018 07:32

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.

Posted by Lieven De Foor on 05-Jul-2018 07:42

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.

Posted by Laura Stern on 05-Jul-2018 08:08

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.

Posted by Laura Stern on 05-Jul-2018 08:09

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

Posted by Lieven De Foor on 05-Jul-2018 08:15

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

Posted by Laura Stern on 05-Jul-2018 08:29

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.

Posted by jquerijero on 05-Jul-2018 09:21

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.

Posted by Lieven De Foor on 05-Jul-2018 09:47

[quote user="Laura Stern"]

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

[/quote]
Well yes I think you should.
I would really like some more technical documentation on design decisions and the way the .NET bridge works/is implemented.
To investigate issues I frequently take a look at the Microsoft reference source (https://referencesource.microsoft.com/) to see how they implemented certain things, and from time to time that gives some valuable insights...

This thread is closed