GetHashCode   zodpovězená otázka

C#, VB.NET

Zdravím,

metoda GetHashCode slouží pro porovnávání oběktů (jestli jsem to z dokumentace správně pochopil) kde se ale tento "kód/číslo" vezme? Jak se generuje? Podle čeho?

Děkuji

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Prostě se vypočítá nějakou interní funkcí Frameworku, jejíž mechanizmus vás nemusí zajímat. Každopádně metodu lze přepsat a vytvořit algoritmus vlastní, např. udělat hash celého serializovaného objektu, nebo sečíst HashCode všech členů třídy.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Ano, mě by spíš zajímalo jestli je to na principu Random, nebo je to nějaká pozice objektu v paměti, a podobně.

Každopádně děkuji za odpověd :-)

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

Tak na princípe random to nebude, pretože dve rovnaké hodnoty musia mať vždy rovnaký HashCode. Taktiež si myslím, že to nebude ani podľa pozícíe objektu v pamäti, pretože po presune položky by sa tým pádom tiež zmenil HashCode, čo je neprípustné.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Pokud se použije standardní frameworkový mechanismus, tak se to podle pozice v paměti počítá. V okamžiku, kdy se poprvé zavolá GetHashCode, hodnota se spočítá a uloží do hlavičky objektu na heapu. Takže pokud se objekt přesune, ta hodnota se nezmění ani neztratí, prostě je tam.

Jen pro zajímavost - každý objekt má (v 32bit prostředí; v 64bit je vše krát 2) hlavičku velikosti 8 bajtů. První 4 bajty je reference na takzvanou Method Table, což je tabulka virtuálních metod a je to také identifikátor datového typu.

Následující 4 bajty se používají právě pro uložení HashCode, a též pro informaci o tom, zda-li na objektu je zámek (třída Monitor).

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Tak potom sa ospravedlňujem za zavádzajúcu informáciu. Každopádne, by ma zaujímalo, ako sa dá zaistiť, že ak na tú istú adresu neskôr dá runtime iný objekt a potom na ňom niečo zavolá GetHashCode, aby nevyšiel rovnaký hash. Prípadne, ak viete nejaký zdroj, kde by som sa dozvedel viac o tom algoritme, aj/alebo všeobecne o interných princípoch runtime .net frameworku, mohli by ste sem napísať odkaz?

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

Dva objekty samozřejmě mohou vrátit stejný hash. Říká se tomu kolize.

Při porovnávání se v .NETu (na rozdíl od kryptografie, tam jsou hashe podstatně delší) nespoléhá na to, že dvě různé hodnoty budou mít vždy různý hash.

Hash se používá jen na místech, kde se ukládají metody do hashovací tabulky (např. Dictionary, HashTable atd.). Např. Dictionary, který slouží k ukládání dvojic klíč-hodnota si v sobě drží tabulku (typicky nějaké úchylné velikosti, např. 19 - jsou to prvočísla). Pokud tam chcete přidat objekt, spočítá se jeho hash, zjistí se zbytek po dělení 19 (resp. aktuální velikostí tabulky) a objekt se uloží na to místo. Může se stát, že dvěma různým objektům vyjde stejný hash, ale klidně i pro objekty s různým hashem se stane, že se díky dělení velikostí tabulky dostanou na stejné místo. Hashovací tabulka má typicky způsoby, jak tohle řešit, typicky si prvky, které se nevejdou, ukládá někam vedle. Pokud je těch prvků vedle víc, nebo je tabulka zaplněná třeba z 60% (pak už začíná být kolizí znatelný počet), hashtabulka se sama zvětší a prvky přesype na nové pozice do nového pole. Když se v tabulce hledá, z hledané hodnoty se spočítá hash a hledá se, jestli v tabulce je stejný objekt - tam se už neporovnává jen podle hashe, ale zavolá se standardní metoda Equals. Hash je jen pro nalezení místa, kde objekt možná je, v konstantním čase.

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

Myslím že to, že dva různé objekty budou mít stejný HashCode je tak mizivá pravděpodobnost, že ji lze zcela ignorovat.

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

Tak, jak jste tu větu napsal, to neplatí - dva různé objekty mívají často stejný hashcode, např. dva různé stringy se stejným obsahem.

.NETu ani nevadí, když dva různé objekty, které se nerovnají (Equals vrací false), mají stejný hashcode.

Tady bych si netroufl tuto možnost zcela ignorovat, jsou to jen 4 miliardy možností. V kryptografii, kde mají hashe 128 bitů a víc, to už je něco jiného. Ale 32 bitů je pořád celkem málo.

Vemte si narozeninový paradox, možných dat narození v roce je 366, ale mezi 23 lidmi máte více než 50% pravděpodobnost, že dva se narodili ve stejný den.

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

Myslel jsem data, ne ukazatel na stejný objekt (Equals).

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

Random to být nesmí, hashcode musí vyjít pro stejnou hodnotu vždy stejně, musí to být deterministické.

Standardní frameworkový mechanismus je dost komplikovaný, ale prakticky jediné, z čeho může vyjít, je datový typ objektu a jeho pozice v paměti. Takže asi tak.

Třídy jako např. String tuto metodu přepisují a počítají ty hodnoty ze svých dat.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • 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