Struktury v Dictionary a For Each cyklus

Tomáš Herceg       22.07.2007       VB.NET       14186 zobrazení

Dnes jsem narazil na další záludnost .NET Frameworku - ve skutečnosti to není záludnost, je to zcela logické, ale rozhodně ne samozřejmé. Pokud používáte generický objekt Dictionary, což je jakýsi slovník klíč - hodnota, občas potřebujete projít všechny jeho položky a něco s nimi provést (např. uložit je do souboru). Není nic jednoduššího než cyklus For Each:

Structure CustomData       'datová struktura s daty
    Dim Id As Integer, Name As String, Description As String, Verze As Integer
End Structure

Dim dic As New Dictionary(Of String, CustomData)    'silně typovaný slovník

Public Sub ProjitSlovnik()	'vypsat všechny položky ve slovníku
    For Each c As CustomData In dic.Values
        MsgBox(c.Name & " " & c.Description)
    Next
End Sub

Navíc si při deklaraci zvolíte datové typy klíče i dat a už v době psaní kódu vám Visual Studio doplňuje možnosti, protože je datový typ známý v době kompilace. Takovému způsobu říkáme strong-typing (silné typování).

Funguje to naprosto perfektně, je to rychlé a pohodlné. Až do chvíle, kdy potřebujete v cyklu změnit obsah dat - pokud jde o strukturu, máme problém. Tyto typy se totiž nepředávají referencí (adresou), ale hodnotou. Pokud tedy změníme uvnitř cyklu data, změna se neprojeví. Slovník totiž vrátí kopii dat a ne odkaz na původní položku. Je to stejné jako při předávání argumentů procedury přes ByRef a ByVal.

    Public Sub ZmenitData()
        Dim d As New CustomData()       'vytvořit fiktivní položku
        d.Name = "test"
        dic.Add("klic", d)

        For Each c As CustomData In dic.Values   'nastavit všem položkám jméno "nazdar lidi"
            c.Name = "nazdar lidi"
        Next

        MsgBox(dic("klic").Name)        'pokud vypíšeme jméno, vrátí se "test", změna ve For Each cyklu se neprojevila
    End Sub

Možná vás napadne, že to můžeme obejít. Třeba si vytvoříme proměnnou, do ní nejdříve vytáhneme data ze slovníku, změníme je a pak proměnnnou vrátíme zpět do slovníku. Ale to také nepůjde - skončíme s chybovou hláškou "Kolekce byla upravena. Operace výčtu pravděpodobně nebude spuštěna." (pokud máte anglický .NET framework, tak "Collection was modified; enumeration operation may not execute.").

Pokud máme obyčenjou kolekci, případně List a jemu podobné, můžeme procházet pomocí indexů - For i As Integer = 0 To seznam.Count - 1. U slovníku to však nejde - máme jen kolekci hodnot a klíčů. Ta se však ale nesmí změnit.

Jak tedy z toho ven? Ze struktury udělat třídu a do slovníku ukládat objekty této třídy. Ty se totiž vždy předávají referencí, takže je můžeme krásně měnit, změna se projeví a vše je v pořádku.

Class CustomData       'třída s daty
    Public Id As Integer, Name As String, Description As String, Verze As Integer
End Class

Její členy musíme změnit na Public nebo z nich udělat vlastnosti (což bych doporučil spíš, máme totiž kontrolu nad přiřazováním hodnot a máme prostředek přiřazení zamezit, pokud je to nutné).

A ještě jeden tip na závěr - pokud napíšete ve Visual Studiu slovo Property a stisknete tabulátor, automaticky se vloží Code snippet s celou konstrukcí vlastnosti. Doplníte pouze název lokální proměnné, datový typ a název vlastnosti. Snadněji to již opravdu nejde.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Diskuse: Struktury v Dictionary a For Each cyklus

cau, jenom bych te trochu opravil. jedna se o "strong typing". strongly je prislovce a znamena "silně"

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Opraveno.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback