Divi vienādi “Jāņi”

Hash kods ir interesanta padarīšana un parasti šo metodi izmanto, lai aprēķinātu objekta hash kodu kādā no hash funkcijas balstītām datu struktūrām, piemēram, HashSet<T> vai Dictionary<K, V> vai tam līdzīgās struktūrās. Hash kods šajās datu struktūrās tiek izmantots, lai optimizētu meklēšanas operāciju.

However ar hash kodiem jābūt uzmanīgiem.

Parasti kā rāda pieredze viens no code-smells ir struktūru (struct) pielietošana. Viss ir labi, bet ir jāsaprot tās side-effekti neskatoties uz to performances (struktūras parasti glabājas tur par stekā pretstatā references tipiem, kuri atrodas heap’ā) un kind-of maintainability (struktūras parasti pēc definīcijas ir immutable) benefitiem.

Anyway, pieņemsim, ka ir sekojoša klase, kas implementēta kā struktūra:

 

public struct Client
{
    public string Name;
    public string Surname;
    public string Code;
    public DateTime BirthDate;
}

 

Pieņemsim, ka ir definētas pilnīgi dažādas klienta entity instances:

 

var client = new Client
                 {
                     Name = "Janis",
                     Surname = "Berzins",
                     BirthDate = new DateTime(1999, 1, 1),
                     Code = "1234567890"
                 };
 
var client2 = new Client
                  {
                      Name = "Janis",
                      Surname = "Kalnins",
                      BirthDate = new DateTime(1978, 4, 1),
                      Code = "0987654321"
                  };

 

Pārbaudām hash kodu šī abām instancēm:

 

Console.WriteLine(client.GetHashCode().ToString());
Console.WriteLine(client2.GetHashCode().ToString());

 

Iznākums nav diez ko iepriecinošs :)

 

image

 

Hash kodam ir jāapmierina pavisam tikai 3 noteikumi:

  1. Ja divi objekti ir vienādi (== operators), tad tiem ir jāģenerē vienādi hash kodi. Pretējā gadījumā hash kods nevar tikt izmantots, lai tos meklētu dažādās datu kopās.
  2. X.GetHashCode() objektam X ir jābūt neatkarīgam no instances stāvokļa. Tas nozīmē, ka pēc X objekta izveides neskatoties kādas tik metodes nav izsauktas, objektam ir jāatgriež viens un tas pats hash kods. Tas arī nodrošina, ka objekts vienmēr tiek ievietots pareizajā vietā (bucket).
  3. Hash kodam jāģenerējas izmantojot visu pieejamo integer spektru. Šāda veida algoritms nodrošina pietiekamu datu struktūras optimizēšanu.

 

Kas patiesībā notiek abu “Jāņu” hash koda ģenerācijas laikā var izlasīt Microsoft .Net Framework source koda anotācijā (reāls izvilkums no platformas source code):

 

/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex.  We look
**        for the first non-static field and get it's hashcode.  If the type has no
**        non-static fields, we return the hashcode of the type.  We can't take the
**        hashcode of a static member because if that member is of the same type as
**        the original type, we'll end up in an infinite loop.
**Returns: The hashcode for the type.
**Arguments: None.
**Exceptions: None.
==============================================================================*/

 

Tātad patiesībā hash koda ģenerācija “Jāņu” gadījumā notiek pēc pirmā non-static lauka šajā struktūrā – Name. Savukārt šis uzstādījums apgalvo, ka visiem “Jāņiem” būs vienāds hash kods, kas arī apliecinās dzīvē.

Kā jau visam šajā pasaulē cilvēks ir atradis skaidrojumu, tā arī šai Microsoft platformas parādībai. Platformas dizaineri ir System.ValueType objektā ieguldījuši visas zināšanas, kas viņiem bija un ir, lai uzģenerētu hash kodu tipam, par kuru viņiem nebija ne mazākās nojausmas.

Ja jūsu definētais tips nepiedalās nekādās datu struktūrās, kur nepieciešams definēt atslēgas, tad hash koda ģenerācija parasti nav nepieciešama vispār. Hash koda ģenerācijas pārrakstīšana retāk ir nepieciešama references tipa objektiem, kur hash koda ģenerācijai tiek izmantots iekšējais objekta instances identifikators.

 

 

Cerams, ka noderēs!

Published Monday, September 12, 2011 11:48 PM by valdis.iljuconoks
Filed under: , , ,

Leave a Comment

(obligāts) 
(obligāts) 
(brīvizvēles)
(obligāts)