Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Hanz 15. 02. 2015, 14:38:26

Název: C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Hanz 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.
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Radek Miček 15. 02. 2015, 15:55:46
Citace
necekane IndexOutOfRangeException u List<T>

To je zvláštní, neboť při indexaci List<T> vyhazuje ArgumentOutOfRangeException.
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Tomáš Roll 15. 02. 2015, 16:07:05
Kdepak, ArguementOutOfRangeException znamená, že je argument metody mimo rozsah.
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Tomáš Roll 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?
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Radek Miček 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
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Hanz 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
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Radek Miček 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.
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Tomáš Roll 15. 02. 2015, 17:35:14
Jo, máš pravdu. IndexOutOfRangeException  vyhazuje např. pole, ne List<T>. Vyzkošeno.
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Hanz 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.
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Radek Miček 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.
                    }
                }
Název: Re:C# - necekane IndexOutOfRangeException u List<T>
Přispěvatel: Hanz 15. 02. 2015, 18:05:57
Strašně moc jste mi pomohl, děkuji i Tomášovi.
H.