Care to review my first hash map?
(I'm assuming you're implementing your own hashtable as an exercise/kata instead of using the CLR's, as I haven't seen anything unique here that justifies rolling your own.)

Here's some feedback:


HashMap should implement core interfaces and functionality as other .NET containers do (e.g.: IEnumerable&lt;T&gt;, IDictionary&lt;TKey,TValue&gt;, provide an enumerator implementation). As a guide, look at the Dictionary&lt;TKey,TValue&gt; class and see what interfaces it implements. I'd expect your code to have a similar level of service;
_blocks should be a List instead of an array, and its capacity (NumberOfBlocks) should be passed optionally through an optional constructor argument. Same applies to the equality comparer. Notice that these initial values seem very, very high - allocating a 42950-Entry[] array right off the bet for an empty container, and an additional 100,000 Entry array at first addition;
Why cast hashCode to uint?
Notice the duplicate code between Add and ContainsKey. This should be cleanly refactored;
blockIndex's and slotIndex's calculations do not seem correct. For example, you are dividing by 100,000, so this will work because int.MaxValue &lt; 100000 * 100000. However, if you make this configurable and a lower value is used, you could go past your _blocks size. You should use modulo instead of division. Also, slotIndex will always be zero (or 1 due to rounding) as (hashCode - blockIndex * BlockSize) == (hashCode - hashCode/BlockSize * BlockSize) == (hashCode - hashCode) == 0. NumberOfBlocks is not used at all here, which is weird;
You should use LinkedList instead of rolling your own linked list (again, I'm assuming you're writing some exercise code, otherwise it's a must). Or at least you should define properties instead of exposing the values as public members;
Don't throw Exception. Create your own custom exception with a proper name;
Setting the entry variable in the if statement in Add is needless and just reduces readability.
The while loop in Add is a bit weird. Why do you need to check entry and entry.Next? I think you meant entry.Next only.
Setting entry at the end of the while look is needless and just reduces readability. I'd actually rename entry to previous for clarity.


Did you write any unit tests for this? Make sure you do so.

EDIT: typo: CRL => CLR