A lista belső végrehajtásának mellékhatása
A lista belső végrehajtásának mellékhatása
Ha előzetesen egy listát -u-t csinálsz elő, akkor a hurok belsejében lévő ismétlődő lap nagyon megkedvelt, mert ez a helyes út az InvalidOperationException eléréséhez. És most a rejtvény: mit gondolsz, mi fog történni a következő kóddal:
A helyes válasz: ez a kód jól működik. A konzolon látható:
A megoldás a List osztály belső megvalósításában rejlik (lásd az MS.NET és a Mono 3.10 megvalósítását). Az iteráció során a Listunknak valahogy nyomon kell követnie, hogy valaki megváltoztatta-e azt a következő iteráción belül. Ehhez használja a _version privát mezőt. Minden művelet esetén a _verzió növekszik 1-vel. Ha egy ciklusszámlálót hoz létre, akkor ezt az értéket megjegyzi. és minden alkalommal, amikor MoveNext hívásra kerül, ellenőrzi. hogy a verziószám nem változott. Ha valaki megváltoztatta a gyűjtemény elemeit, akkor az InvalidOperationException dobásra kerül.
De a fenti kód minden kivétel nélkül jól működik. Hogy van így? A megoldás egyszerű: a _version tárolására int használatos. És mi fog történni, ha az int-változó pontosan 2-szer 32-szer nő? Visszatér az eredeti értékéhez. A példában a belső hurok (int.MinValue - int.MaxValue) pontosan 2 32-1-szer változik a rossz _version. És a vonallista. A (3) hozzáadása hozzáad egy új elemet a laphoz, és a végső változatot a _version-ban végzi. amely visszaadja annak eredeti értékét. Ennek eredményeképpen a következő MoveNext () hívásakor senki sem gyanítja, hogy valamit megváltoztattunk. A tökéletes bűnözés.
A dokumentáció elmondja. hogy kivételt kell adni, ha valaki megváltoztatta a gyűjteményt. Így hivatalosan ez a példa egy kis NET-hibát szemléltet. Azonban nem érdemes aggódni ezzel kapcsolatban: a valóságos probléma hasonló megbomlásának valószínűsége elég kicsi. Nem szükséges figyelembe venni az ilyen viselkedést, és valahogy figyelembe kell venni, mert ezután megváltozhat (pl. a _version 64-bites lesz).