-1

I have a code that deletes the textbox and datetimepicker i create in a panel... delete code is working for all the TEXTBOX but when its time to delete the datetimepickers it does not delete all the datetimepicker. Example: there are 4 textbox and 4 datetimepickers when it runs the code the panel will delete all 4 textbox but deletes 2 datetiepickes only. I really cant find out what is wrong. Please help me... Thanks!

code is here:

 For Each ctrlTxt As TextBox In panelGroupDependent.Controls.OfType(Of TextBox)()            
        ctrlTxt.Dispose()
 Next
For Each ctrlDtp As DateTimePicker In panelGroupDependent.Controls.OfType(Of DateTimePicker)()
        ctrlDtp.Dispose()
 Next
Carl
  • 23
  • 1
  • 1
  • 6
  • So what actually happens? Have you debugged the code, i.e. set a breakpoint and stepped through it to make sure each line that you expect is actually executed and that every value is what you expect? To be honest, I'm surprised that that code works at all. It looks like it's modifying a collection while enumerating it to me. Try adding a `ToArray` call after each `OfType`, e.g. `panelGroupDependent.Controls.OfType(Of DateTimePicker)().ToArray()`, and see whether that makes a difference. – jmcilhinney Dec 14 '18 at 04:45
  • @jmcilhinney it works now after putting a .ToArray() thanks man how did it work? hahahhaha – Carl Dec 14 '18 at 04:57
  • I've added an answer to that effect, including a full explanation. – jmcilhinney Dec 14 '18 at 05:41
  • https://stackoverflow.com/q/2014286/17034 – Hans Passant Dec 14 '18 at 06:29

1 Answers1

0

As it stands, you are modifying a collection as you are enumerating it, which is not allowed. A For Each loop enumerates a collection so you are not allowed to add or remove items within the loop. When you dispose a control, it is removed from its parent container and thus you are modifying the Controls collection of that parent.

The OfType method doesn't actually generate a new collection of items but rather enumerates the collection it's called on and yields the items of the specified type one by one. As such, enumerating the result of OfType means enumerating the source collection at the same time.

By calling ToArray, you complete the enumeration of the source collection first and populate an array with the items of the specified type, then enumerate that array using the For Each loop. Disposing the controls has no effect on the array so there's no issue.

For Each ctrlTxt In panelGroupDependent.Controls.
                                        OfType(Of TextBox)().
                                        ToArray()
    ctrlTxt.Dispose()
Next

For Each ctrlDtp In panelGroupDependent.Controls.
                                        OfType(Of DateTimePicker)().
                                        ToArray()
    ctrlDtp.Dispose()
Next

Note that there is also no need to declare the type of the loop control variables as it can be inferred.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46