Creating a Hash Code for a Data Type

Problem
You have created a class or structure that will be used as a key in a Hashtable or Dictionary<T,U>. You need to overload the GetHashCode method in order to return a good distribution of hash values (the Discussion section defines a good distribution of hash values). You also need to choose the best hash-code algorithm to use in the GetHashCode method of your object.

        public static void CreateHashCodeDataType()
        {
            SimpleClass simpleClass = new SimpleClass("foo");

            Hashtable hashTable = new Hashtable();
            hashTable.Add(simpleClass, 100);

            Dictionary<SimpleClass, int> dict = new Dictionary<SimpleClass, int>();
            dict.Add(simpleClass, 100);
        }

        public class SimpleClass
        {
            private string text = "";

            public SimpleClass(string inputText)
            {
                text = inputText;
            }

            public override int GetHashCode()
            {
                return (ShiftAndAddHash(text));
            }

            public int ShiftAndAddHash(string strValue)
            {
                int hashCode = 0;

                foreach (char c in strValue)
                {
                    hashCode = (hashCode << 5) + (int)c + (hashCode >> 2);
                }

                return (hashCode);
            }
        }

        public int SimpleHash(params int[] values)
        {
            int hashCode = 0;
            if (values != null)
            {
                foreach (int val in values)
                {
                    hashCode ^= val;
                }
            }

            return (hashCode);
        }

        public int FoldingHash(params long[] values)
        {
            int hashCode = 0;
            if (values != null)
            {
                int tempLowerVal = 0;
                int tempUpperVal = 0;
                foreach (long val in values)
                {
                    tempLowerVal = (int)(val & 0x000000007FFFFFFF);
                    tempUpperVal = (int)((val >> 32) & 0xFFFFFFFF);
                    hashCode^= tempLowerVal ^ tempUpperVal;
                }
            }

            return (hashCode);
        }

        public int ContainedObjHash(params object[] values)
        {
            int hashCode = 0;
            if (values != null)
            {
                foreach (int val in values)
                {
                    hashCode ^= val.GetHashCode();
                }
            }

            return (hashCode);
        }

        public int CryptoHash(string strValue)
        {
            int hashCode = 0;
            if (strValue != null)
            {
                byte[] encodedUnHashedString = 
                    Encoding.Unicode.GetBytes(strValue);

                byte[] key = new byte[16];
                RandomNumberGenerator.Create().GetBytes(key);

                MACTripleDES hashingObj = new MACTripleDES(key);
                byte[] code = 
                    hashingObj.ComputeHash(encodedUnHashedString);

                // use the BitConverter class to take the 
                // first 4 bytes and use them as an int for
                // the hash code
                hashCode = BitConverter.ToInt32(code,0);    
            }

            return (hashCode);
        }

        public int CryptoHash(long intValue)
        {
            int hashCode = 0;
            byte[] encodedUnHashedString = 
                Encoding.Unicode.GetBytes(intValue.ToString());

            SHA256Managed hashingObj = new SHA256Managed();
            byte[] code = hashingObj.ComputeHash(encodedUnHashedString);

            // use the BitConverter class to take the 
            // first 4 bytes and use them as an int for
            // the hash code
            hashCode = BitConverter.ToInt32(code,0);    

            return (hashCode);
        }

        public int ShiftAndAddHash (string strValue)
        {
            int hashCode = 0;
            
            foreach (char c in strValue)
            {
                hashCode = (hashCode << 5) + (int)c + (hashCode >> 2);
            }
            
            return (hashCode);
        }

        public int CalcHash(short someShort, int someInt, long someLong,
            float someFloat, object someObject)
        {
            int hashCode = 7;
            hashCode = hashCode * 31 + (int)someShort;
            hashCode = hashCode * 31 + someInt;
            hashCode = hashCode * 31 + 
                (int)(someLong ^ (someLong >> 32));
            long someFloatToLong = (long)someFloat;
            hashCode = hashCode * 31 + 
                (int)(someFloatToLong ^ (someFloatToLong >> 32));

            if (someObject != null)
            {
                hashCode = hashCode * 31 + 
                    someObject.GetHashCode();
            }

            return (hashCode);
        }

        public int ConcatStringGetHashCode(int[] someIntArray)
        {
            int hashCode = 0;
            StringBuilder hashString = new StringBuilder();

            if (someIntArray != null)
            {
                foreach (int i in someIntArray)
                {
                    hashString.Append(i.ToString() + "^");
                }
            }
            hashCode = hashString.GetHashCode();

            return (hashCode);
        }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Advertisements