File: Base\MS\Internal\BaseHashHelper.cs
Project: wpf\src\WindowsBase.csproj (WindowsBase)
//---------------------------------------------------------------------------
//
// <copyright file="BaseHashHelper.cs" company="Microsoft">
//    Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// </copyright>
//
//
// Description: Static class to help work around hashing-related bugs.
//
//---------------------------------------------------------------------------
 
using System;
using System.Reflection;                // Assembly
using System.Collections.Specialized;   // HybridDictionary
using MS.Internal.WindowsBase;          // [FriendAccessAllowed]
 
namespace MS.Internal
{
    [FriendAccessAllowed]   // defined in Base, used in Core and Framework
    internal static class BaseHashHelper
    {
        static BaseHashHelper()
        {
            // register bad types from WindowsBase
            MS.Internal.Hashing.WindowsBase.HashHelper.Initialize();
        }
 
        [FriendAccessAllowed]   // defined in Base, used in Core and Framework
        internal static void RegisterTypes(Assembly assembly, Type[] types)
        {
            HybridDictionary dictionary = DictionaryFromList(types);
 
            lock(_table)
            {
                _table[assembly] = dictionary;
            }
        }
 
        // Some types don't have reliable hash codes - the hashcode can change
        // during the lifetime of an object of that type.  Such an object cannot
        // be used as the key of a hashtable or dictionary.  This is where we
        // detect such objects, so the caller can find some other way to cope.
        [FriendAccessAllowed]   // defined in Base, used in Core and Framework
        internal static bool HasReliableHashCode(object item)
        {
            // null doesn't actually have a hashcode at all.  This method can be
            // called with a representative item from a collection - if the
            // representative is null, we'll be pessimistic and assume the
            // items in the collection should not be hashed.
            if (item == null)
                return false;
 
            Type type = item.GetType();
            Assembly assembly = type.Assembly;
            HybridDictionary dictionary;
 
            lock(_table)
            {
                dictionary = (HybridDictionary)_table[assembly];
            }
 
            if (dictionary == null)
            {
                dictionary = new HybridDictionary();
 
                lock(_table)
                {
                    _table[assembly] = dictionary;
                }
            }
 
            return !dictionary.Contains(type);
        }
 
        // populate a dictionary from the given list
        private static HybridDictionary DictionaryFromList(Type[] types)
        {
            HybridDictionary dictionary = new HybridDictionary(types.Length);
            for (int i=0; i<types.Length; ++i)
            {
                dictionary.Add(types[i], null);
            }
 
            return dictionary;
        }
 
        static HybridDictionary _table = new HybridDictionary(3);
    }
}