foreach działa tylko na co 2 element

Odpowiedz Nowy wątek
2018-03-28 20:34
0

Witam, problem dokładnie taki jak w temacie- pętla foreach usuwa tylko co 2 button które są w panelu. Projekt robiony w winforms

foreach(Control control in panelMapCreate.Controls)
            {
                Controls.Remove(control);
                control.Dispose();
            }

Dodam że wszystkie te buttony są również tworzone podczas działania programu

int wysokosc = Int32.Parse(comboBoxWysokosc.Text);
            int szerokosc = Int32.Parse(comboBoxSzerokosc.Text);
            for (int i = 0; i < wysokosc; i++)
            {
                for (int j = 0; j < szerokosc; j++)
                {
                    Button newButton = new Button();
                    newButton.Location = new Point(4 + 50 * j, 4 + 50 * i);

                    newButton.Height = 40;
                    newButton.Width = 40;
                    panelMapCreate.Controls.Add(newButton);
                    newButton.Show();
                }
            }

Ktoś ma jakiś pomysł?

Pozostało 580 znaków

2018-03-28 20:39

Nie usuwaj elementów kolekcji w foreachu

The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.

unpredictable side effects

edytowany 5x, ostatnio: WeiXiao, 2018-03-28 20:41

Pozostało 580 znaków

2018-03-28 20:56
0

Dzięki, zrobiłem to już while'em.

while (panelMapCreate.Controls.Count>0)
                {
                    Controls.Remove(panelMapCreate.Controls[0]);
                    panelMapCreate.Controls[0].Dispose();
                }

Mam nawet pewną ideę jak to może działać że usuwa tylko co 2 no bo skoro foreach działa na zasadzie iteracji(nie wiem czy tak jest tylko tak zakładam) w momencie kiedy usunie element 0 element 1 staje się 0. Wtedy foreach chce usunąć element początkowo 1 pomijając aktualnie 0 usuwając element który był początkowo 2 itd.
Może ktoś mądry to potwierdzi jeśli mam rację albo obali i poda poprawne wyjaśnienie.
Nie mniej problem rozwiązany(właściwie niepotrzebnie założony wątek), ale jeśli ktoś ma chęci pomyszkować lub zna odpowiedź dlaczego tak się dzieje chętnie się dowiem ;)

@WeiXiao: za Twoim drugim "lub" brakuje linka. - Silv 2018-03-28 21:16
@Silv: o jeden lub zbyt wiele, dzięki :p - WeiXiao 2018-03-28 21:17
@WeiXiao: po co dałeś linka do jakiejś klasy z Windows Workflow Foundation? - somekind 2018-03-29 01:45
@somekind: Szczerze nic innego się nie doszukałem nt. implementacji foreacha. To źle? - WeiXiao 2018-03-29 13:33
No, bo to nie ma związku z instrukcją foreach, o której mowa w wątku, to po prostu jakaś klasa z dość rzadko używanego frameworka. "Implementacja" foreach znajduje się w kompilatorze, nie w źródłach .NET. - somekind 2018-03-29 18:34

Pozostało 580 znaków

2018-03-29 02:04
4
Foka napisał(a):

Mam nawet pewną ideę jak to może działać że usuwa tylko co 2 no bo skoro foreach działa na zasadzie iteracji(nie wiem czy tak jest tylko tak zakładam) w momencie kiedy usunie element 0 element 1 staje się 0. Wtedy foreach chce usunąć element początkowo 1 pomijając aktualnie 0 usuwając element który był początkowo 2 itd.

Mniej więcej tak, tylko sprawa jest trochę bardziej skomplikowana, bo foreach to tylko taki cukier składniowy do korzystania z Enumeratora: https://www.dotnetperls.com/getenumerator
Czyli generalnie wszystko zależy od implemetacji Enumeratora właśnie, no ale że zazwyczaj w środku jest jakaś tablica, a MoveNext zwiększa po prostu indeks, z którego później korzysta właściwość Current, to jest tak, jak napisałeś - indeksy w foreach idą do przodu, ale na skutek usuwania elementy zmieniają swoje indeksy na mniejsze.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2018-03-29 09:15
1

Ja tu czegoś chyba nie ogarniam. Iterujesz po panelMapCreate.Controls, a usuwasz z Controls. Te buttony są dodane i do panelMapCreate i do kontrolki w której są te metody? Jeżeli tak, to nie powinno tak być, jeżeli nie to nie powinno to w ogóle działać.

edytowany 1x, ostatnio: Sarrus, 2018-03-29 09:15

Pozostało 580 znaków

2018-03-29 10:46
0

No a to nie jest tak że jak dodaje buttona do panelu to jest on jednocześnie dodawany do kolekcji kontrolek panelu i do kolekcji kontrolek całej formy?

Aż muszę sprawdzić. - Sarrus 2018-03-29 10:54

Pozostało 580 znaków

2018-03-29 11:00
0

Generalnie oba poniższe sposoby działają.

Controls.Remove(panelMapCreate.Controls[ilosc]);
 panelMapCreate.Controls[ilosc].Dispose();

i tak

 Control control = panelMapCreate.Controls[ilosc];
 panelMapCreate.Controls.Remove(control);
  control.Dispose();

Pomimo tego że buttony kontrolki które usuwam są tylko w kolekcji panelu. Przynajmniej tak się wydaję gdy sprawdzę ich ilość w ten sposób

labelile.Text = Controls.Count.ToString();
labelile.Text += " " + panelMapCreate.Controls.Count.ToString();

Pozostało 580 znaków

2018-03-29 11:04
1

Pierwszy przykład jest błędny, bo Dispose wywołujesz na innej kontrolce.

Jeżeli dodajesz je do kolekcji panelu, to tam są i stamtąd powinieneś je usuwać.

edytowany 1x, ostatnio: Sarrus, 2018-03-29 11:05
Czyli ten 2 sposób jest poprawniejszy, tak? :) - Foka 2018-03-29 11:07
Zdecydowanie - Sarrus 2018-03-29 11:08

Pozostało 580 znaków

2018-03-29 11:13
0

NIe wiem - nie pamietam jak wyglada Controls ale nie ma to przypadkiem metody .Clear()?

Pozostało 580 znaków

2018-03-29 11:56
0

"Calling the Clear method does not remove control handles from memory. You must explicitly call the Dispose method to avoid memory leaks." Nie wiem czym dokładnie są handles, ale mimo to nie brzmi to zachęcająco

Pozostało 580 znaków

2018-03-29 12:11
0

Chodzi o uchwyty do zasobów natywnych, którymi .NET nie zarządza.

edytowany 1x, ostatnio: Sarrus, 2018-03-29 12:11

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0