private HashCodeHelper HashReadOnlyDictionary <TKey, TValue>( IReadOnlyDictionary <TKey, TValue> dictionary) { HashCodeHelper result = this; if (dictionary == null) { // We cannot just use the current hash code value as is. // We have to hash null and thus change the current hash code. // Consider the following collection of dictionaries: // { { "a": 1 }, { "b": 2 } } // { { "a": 1 }, null, { "b": 2 } } // They would result in the same hash code if we didn't hash null. result = result.Hash <object>(null); } else { result = result.HashUnorderedCollection(dictionary.Keys); // Is there a comparer for the keys? if (!TypeExtensions.HasWorkingDefaultComparer <TKey>()) { // There is no comparer for the keys and thus we cannot sort the key/value pairs. // The best we can do is hash the count, which will ensure // that two dictionaries, having a different count, will // not return the same hash code. result = result.Hash(dictionary.Count); } else { // The keys can be sorted. Sort the key/value pairs by the keys // and then hash the key collection and the value collection, // treating them as ordered collections. var keyValuePairsInOrder = dictionary.OrderBy(_ => _.Key).ToList(); result = result.HashOrderedCollection(keyValuePairsInOrder.Select(_ => _.Key)); result = result.HashOrderedCollection(keyValuePairsInOrder.Select(_ => _.Value)); } } return(result); }
private HashCodeHelper HashUnorderedCollection <TElement>( IEnumerable <TElement> collection) { HashCodeHelper result = this; if (collection == null) { // We cannot just use the current hash code value as is. // We have to hash null and thus change the current hash code. // Consider the following collection of collections: // { { 1, 2 }, {3, 4} } // { { 1, 2 }, null, {3, 4} } // They would result in the same hash code if we didn't hash null. result = result.Hash <object>(null); } else { // Is there a comparer for the element type? // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (!TypeExtensions.HasWorkingDefaultComparer <TElement>()) { // There is no comparer and thus we cannot sort the elements. // The best we can do is hash the element count, which will ensure // that two unordered collections, having a different count, will // not return the same hash code. result = result.Hash(collection.Count()); } else { // There is a comparer; sort the collection and then treat // it as an ordered collection and hash that. This ensures that // two unordered collections that are equal but having a different // order will result in the same hash code. result = result.HashOrderedCollection(collection.OrderBy(_ => _)); } } return(result); }