C# - necekane IndexOutOfRangeException u List<T>

Hanz

C# - necekane IndexOutOfRangeException u List<T>
« kdy: 15. 02. 2015, 14:38:26 »
Dobrý den, prosím pomozte mi - snažím se procházet kolekci a nemůžu přijít na to, proč dochází k přeindexování. Radši pošlu rovnou ukázku kódu.

Mám:

Kód: [Vybrat]
    public event EventHandler<BrickRemovedEventArgs> BrickRemoved;

    public class BrickRemovedEventArgs : EventArgs
    {
        public BrickRemovedEventArgs(int index)
        {
            this.index = index;
        }

        public int index;
    }

dále v threadu na pozadí:

Kód: [Vybrat]
                for ( int i = 0; i < bricks.Count; i ++ )
                {
                    var brick = bricks[i];

                    if ((brick.visible) && brick.IntersectWithCircle(circleX, circleY, circleSize))
                    {
                        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                            new Action(() => BrickRemoved(this, new BrickRemovedEventArgs(i))));
                    }
                }

a dále:

Kód: [Vybrat]
        private void ArkanoidViewModel_BrickRemoved(object sender, BrickRemovedEventArgs e)
        {
            bricks[e.index].visible = false;
        }

Objektů v List<brickInfo> bricks je 24, tedy 0..23. Proč ale tedy program spadne na e.index = 24. Jak by se tam ta hodnota mohla dostat, když indexuju od nuly po bricks.Count? Kontejner nikdo od zalozeni ani v prubehu co do prvku nemeni.

Nevite prosim, kde by mohla byt chyba?
H.


Radek Miček

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #1 kdy: 15. 02. 2015, 15:55:46 »
Citace
necekane IndexOutOfRangeException u List<T>

To je zvláštní, neboť při indexaci List<T> vyhazuje ArgumentOutOfRangeException.

Tomáš Roll

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #2 kdy: 15. 02. 2015, 16:07:05 »
Kdepak, ArguementOutOfRangeException znamená, že je argument metody mimo rozsah.

Tomáš Roll

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #3 kdy: 15. 02. 2015, 16:08:56 »
Dobrý den, prosím pomozte mi - snažím se procházet kolekci a nemůžu přijít na to, proč dochází k přeindexování. Radši pošlu rovnou ukázku kódu.
...
Objektů v List<brickInfo> bricks je 24, tedy 0..23. Proč ale tedy program spadne na e.index = 24. Jak by se tam ta hodnota mohla dostat, když indexuju od nuly po bricks.Count? Kontejner nikdo od zalozeni ani v prubehu co do prvku nemeni.

Nevite prosim, kde by mohla byt chyba?
H.

A zkoušels ten kod osekávat až na funkční minimum?

Radek Miček

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #4 kdy: 15. 02. 2015, 16:21:33 »
Kdepak, ArguementOutOfRangeException znamená, že je argument metody mimo rozsah.

A on není? Viz https://msdn.microsoft.com/en-us/library/0ebtbkkc%28v=vs.110%29.aspx


Hanz

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #5 kdy: 15. 02. 2015, 16:28:20 »
Ano je a proto vývojáři C# tuto výjimku vytvořili. Nedokážu si představit, jakou paseku by to udělalo v c/c++.

Otázka byla, jak vůbec mohlo dojít v rámci for cyklu (?) k přeindexování.

Asi mi nezbyde, co navrhnul Tomáš Roll - osekat na minimum a tak přijdu, kde je chyba.

Díky

Radek Miček

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #6 kdy: 15. 02. 2015, 16:38:46 »
Ano je a proto vývojáři C# tuto výjimku vytvořili. Nedokážu si představit, jakou paseku by to udělalo v c/c++.

Otázka byla, jak vůbec mohlo dojít v rámci for cyklu (?) k přeindexování.

Asi mi nezbyde, co navrhnul Tomáš Roll - osekat na minimum a tak přijdu, kde je chyba.

Díky

Jen jsem chtěl naznačit, že List<T> výjimku IndexOutOfRangeException nevyhazuje, tudíž ten název tématu nedává smysl.

Tomáš Roll

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #7 kdy: 15. 02. 2015, 17:35:14 »
Jo, máš pravdu. IndexOutOfRangeException  vyhazuje např. pole, ne List<T>. Vyzkošeno.

Hanz

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #8 kdy: 15. 02. 2015, 17:50:22 »
Nechtěl jsem zavést zmatek, omlouvám se.

Zjistil jsem následující:

Kód: [Vybrat]
                for ( int i = 0; i < bricks.Count; i ++ )
                {
                    var brick = bricks[i];
                    // MessageBox.Show(i.ToString());

                    if ((brick.visible) && brick.IntersectWithCircle(circleX, circleY, circleSize))
                    {
                        MessageBox.Show(i.ToString());

                        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                            new Action(() => BrickRemoved(this, new BrickRemovedEventArgs(i))));
                    }
                }

Druhý MessageBox jde od 0 do 23, ale asynchronní volání je schopno vyústit v argument 24 - teď byste byli prosím schopni mi poradit? Jak k tomu mohlo dojít? Šlo by to třeba řešit kritickou sekcí? Jestli prosím víte, poraďte mi. Příště třeba poradím já.

Děkuji
H.

Radek Miček

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #9 kdy: 15. 02. 2015, 17:59:22 »
Nechtěl jsem zavést zmatek, omlouvám se.

Zjistil jsem následující:

Kód: [Vybrat]
                for ( int i = 0; i < bricks.Count; i ++ )
                {
                    var brick = bricks[i];
                    // MessageBox.Show(i.ToString());

                    if ((brick.visible) && brick.IntersectWithCircle(circleX, circleY, circleSize))
                    {
                        MessageBox.Show(i.ToString());

                        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                            new Action(() => BrickRemoved(this, new BrickRemovedEventArgs(i))));
                    }
                }

Druhý MessageBox jde od 0 do 23, ale asynchronní volání je schopno vyústit v argument 24 - teď byste byli prosím schopni mi poradit? Jak k tomu mohlo dojít? Šlo by to třeba řešit kritickou sekcí? Jestli prosím víte, poraďte mi. Příště třeba poradím já.

Děkuji
H.

Hádám, že se to volání vykoná až poté, co cyklus skončil (což je v okamžiku i == 24). Zkusil bych si i okopírovat:

Kód: [Vybrat]
                for ( int i = 0; i < bricks.Count; i ++ )
                {
                    var brick = bricks[i];
                    // MessageBox.Show(i.ToString());

                    if ((brick.visible) && brick.IntersectWithCircle(circleX, circleY, circleSize))
                    {
                        MessageBox.Show(i.ToString());

                        int z = i; // Okopiruji i.
                        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                            new Action(() => BrickRemoved(this, new BrickRemovedEventArgs(z)))); // Zde pouziji z misto i.
                    }
                }

Hanz

Re:C# - necekane IndexOutOfRangeException u List<T>
« Odpověď #10 kdy: 15. 02. 2015, 18:05:57 »
Strašně moc jste mi pomohl, děkuji i Tomášovi.
H.