Reputation: 15
I've made a function to do an iteration on all the controls in a form to check if a control name matches with a string. If it does, I would like to return the control itself as an object as the function value that is passed to the rest of the program.
Here's my work:
Public Function getcontrolType(Optional ByVal controlString As String = "", Optional ByVal parentCtrl As Control = Nothing) As System.Object
Dim returnValue As System.Object
If parentCtrl Is Nothing Then
parentCtrl = MainModelForm
End If
For Each ctrl As Control In parentCtrl.Controls
If ctrl.HasChildren Then
getcontrolType(controlString, ctrl)
End If
If ctrl.Name = controlString Then
returnValue = ctrl.Name
Return returnValue
End If
Next
Return "Can't find control!"
End Function
The issue I'm running into is that the program executes correctly to the point of assigning the returnValue to the ctrl.Name, and then it executes the Return statement and then goes to the End Function. From there though, the code doesn't actually exit the function and instead jumps back to the getcontrolType(controlString, ctrl) line. I'm sure there has to be something off with my iteration (computers are only as smart as you tell them to be!), but I don't understand why it would go to the End Function line and then jump back into the code?
Thanks for any and all help!
Upvotes: 1
Views: 219
Reputation: 10488
I don't understand why it would go to the End Function line and then jump back into the code?
This is to be expected. When a function returns, the execution goes back to the previous stack frame and resumes from where it left. This is exactly what your code does.
The confusing part comes from the fact that your function is recursive. You are under the impression that the code simply moves from the Return
statement line back into a given position within code, similar to a GOTO
operation. But truth is that the stack does in fact go down one frame, back to completing the previous call to the same function.
If you want to check this out, simply run your code in debug mode and watch the value of the returnValue
variable. Right after the code "jumps back", you'll see that it will be pointing to a different value. This is because the execution is now back to completing the parent call, for which the value has been kept in memory.
In fact, that last part is actually one reason why you'd want to be very careful when making recursive calls. The deeper they go, the more memory they require. You can read about it here:
Recursive Procedures (Visual Basic) - MSDN
As of why your actual code doesn't work the way you want, it looks like you never use the returned value of the nested call to getcontrolType
function. Change that part to this instead:
If ctrl.HasChildren Then
Return getcontrolType(controlString, ctrl)
End If
If I may, I would also suggest that you change your function's name to GetControlName
and use System.String
as the return type.
Or better yet: name it GetControl
and have it return the instance of the found control (with return type being System.Windows.Forms.Control
).
EDIT:
Are you aware of the ControlCollection.Find method? It might give you what you want much more efficiently:
Dim controlToFind = parentControl.Controls.Find("myControlName", True).SingleOrDefault();
Upvotes: 2