This tip was submitted to the VS.NET Info Center by member Rick Spiewak. Please let other users know how useful it is by rating it below. Do you have a tip or code of your own you'd like to share? Submit it here.
Many VB developers have probably heard the statement: "VB6 does support full object oriented programming, so it's not a 'real' language." Now with VB7 (VB.NET), OOP is here in all its glory. Well, it's here, but it sure isn't all glory -- at least not when it comes to polymorphism. In this tip, I will show a rather nasty pitfall that can happen when you use polymorphism in VB.NET.
The code below is very simple, very naive. However, it could take several hours of head scratching to figure out what's wrong. Before you paste it into a new console application project, try and figure out why the stack overflow occurs without using the debugger to trace through the execution path.
Module MyModule
Class Parent
Public Overridable Sub p1()
Console.Write("Parent.p1")
End Sub
Public Sub p2()
'blah blah
p1()
'blah blah
End Sub
End Class
Class Child
Inherits Parent
Public Overrides Sub p1()
Console.Write("Child.p1")
MyBase.p2()
End Sub
End Class
Sub Main()
Dim p As Parent
Dim c As Child
p =
Requires Free Membership to View
When you register, you'll begin receiving targeted emails from my team of award-winning writers. Our goal is to provide a unique online resource for developers, architects and development managers tasked with building and maintaining enterprise applications using Visual Basic, C# and the Microsoft .NET platform.
Hannah Smalltree, Editorial Director New Parent()
p.p1() 'OK
p.p2() 'OK
p = New Child()
p.p1() 'stack overflow
p.p2() 'stack overflow
c = New Child()
c.p1() 'stack overflow
c.p2() 'stack overflow
End Sub
End Module
This is not something I discovered by accident. I actually designed it by making use of my understanding of polymorphism. The problem is, it can happen without you knowing in your everyday coding work, whether you like it or not.
So why does the stack oveflow occur?
*Parent.p2() calls Parent.p1() *Parent.p1() is polymorphic because it can be overriden *Child.p1() overrides Parent.p1() so any calls to Parent.p1() will actually call Child.p1() if you have an instance of class Child. *Child.p1() calls MyBase.p2() *MyBase.p2() is actually Parent.p2()
Now if you are still with me, the pitfall comes when you have an instance of class Child and call procedures p1 and p2. Calling p1 produces the following execution flow:
Child.p1 -> Parent.p2 -> Child.p1 -> Parent.p2 -> Child.p1 -> etc.
and the cycle repeats until we have no stack space left. Calling p2 produces the following execution flow:
Child.p2 -> Child.p1 -> Parent.p2 -> Child.p1 -> Parent.p2 -> Child.p1 -> etc.
If you are lost (which is perfectly human given the complexity of the pitfall), then the best way to understand it is to step through the code when the following lines in Sub Main execute:
p = New Parent()
p.p1() 'OK
p.p2() 'OK
p = New Child()
p.p1() 'stack overflow
p.p2() 'stack overflow
c = New Child()
c.p1() 'stack overflow
c.p2() 'stack overflow
Some things to note:
Now for the tip:
The full glory of OOP is now in VB.NET, but so are the nightmares. So be careful, and happy coding!
This was first published in October 2003