Improve lookup perf on immutable dictionaries and sets

This PR improves the performance of lookups (indexer access, Contains, etc.) on both ImmutableDictionary<TKey,TValue> and ImmutableHashSet<T>.  For the former, I've measured upwards of a 40% improvement, and for the latter, upwards of 60%, but it depends significantly on the amount of work required to get hash codes and compare TKey values... the more work required for those operations, the less benefits this change provides.

The reason for this is that, today, other than the costs of getting a hash code / comparing TKey values, a primary cost in looking up values is in traversing the ImmutableSortedDictionary<Int32,HashBucket>.Node tree that backs both dictionaries and sets.  For each node, the sorted dictionary's key needs to be compared against the supplied Int32 key.  This is done using a Comparer<Int32>.Default, which means an interface call through IComparer<T>.Compare.  The comparer returned from Comparer<Int32>.Default is a GenericComparer<Int32>, which implements its Compare method by delegating to a call to Int32's IComparable<T>.CompareTo interface method, for another interface call.  Thus, even though we know we're comparing Int32 values, each comparison actually involves multiple interface calls.

This commit creates a specialized version of ImmutableSortedDictionary'2.Node that sets TKey as Int32.  This allows the new implementation, which is then used by both ImmutableDictionary'2 and ImmutableHashSet'1, to avoid multiple interface calls per node during lookups, doing the Int32 comparisons directly rather than going through Comparer<int>.Default, which in turn goes through Int32's IComparable<T>.CompareTo implementation.  The new code is really just a copy of ImmutableSortedDictionary'2.Node, with Int32 substituted for TKey, and with doing the Int32 comparisons directly rather than going through IComparer<T>.

Even though it's copied code (basically the equivalent of what you'd get with template expansion), it does add a bunch of code to the project.  I think it's worth it for the perf improvements, but let me know if you disagree.
@pgavlin, this is a good suggestion.  Based on that formula, we'd hit Int32.MaxValue nodes well before we reached the limit of what a byte can store, and changing height from an int to a byte effectively decreases the size of the node on both 32-bit and 64-bit by ~10%.  It doesn't affect the micro-benchmarks I've been using, which suggests that code quality doesn't suffer as a result of the change.  Unless there are objections, I'll go ahead with that, but I'll do it as a separate PR just to keep it separate from this change, which is largely orthogonal.