//****************************** // Written by Peter Golde // Copyright (c) 2004-2005, Wintellect // // Use and restribution of this code is subject to the license agreement // contained in the file "License.txt" accompanying this file. //****************************** using System; using System.Collections.Generic; namespace Wintellect.PowerCollections { /// /// A collection of methods to create IComparer and IEqualityComparer instances in various ways. /// internal static class Comparers { /// /// Class to change an IEqualityComparer<TKey> to an IEqualityComparer<KeyValuePair<TKey, TValue>> /// Only the keys are compared. /// [Serializable] class KeyValueEqualityComparer : IEqualityComparer> { private IEqualityComparer keyEqualityComparer; public KeyValueEqualityComparer(IEqualityComparer keyEqualityComparer) { this.keyEqualityComparer = keyEqualityComparer; } public bool Equals(KeyValuePair x, KeyValuePair y) { return keyEqualityComparer.Equals(x.Key, y.Key); } public int GetHashCode(KeyValuePair obj) { return Util.GetHashCode(obj.Key, keyEqualityComparer); } public override bool Equals(object obj) { if (obj is KeyValueEqualityComparer) return object.Equals(keyEqualityComparer, ((KeyValueEqualityComparer)obj).keyEqualityComparer); else return false; } public override int GetHashCode() { return keyEqualityComparer.GetHashCode(); } } /// /// Class to change an IComparer<TKey> to an IComparer<KeyValuePair<TKey, TValue>> /// Only the keys are compared. /// [Serializable] class KeyValueComparer : IComparer> { private IComparer keyComparer; public KeyValueComparer(IComparer keyComparer) { this.keyComparer = keyComparer; } public int Compare(KeyValuePair x, KeyValuePair y) { return keyComparer.Compare(x.Key, y.Key); } public override bool Equals(object obj) { if (obj is KeyValueComparer) return object.Equals(keyComparer, ((KeyValueComparer)obj).keyComparer); else return false; } public override int GetHashCode() { return keyComparer.GetHashCode(); } } /// /// Class to change an IComparer<TKey> and IComparer<TValue> to an IComparer<KeyValuePair<TKey, TValue>> /// Keys are compared, followed by values. /// [Serializable] class PairComparer : IComparer> { private IComparer keyComparer; private IComparer valueComparer; public PairComparer(IComparer keyComparer, IComparer valueComparer) { this.keyComparer = keyComparer; this.valueComparer = valueComparer; } public int Compare(KeyValuePair x, KeyValuePair y) { int keyCompare = keyComparer.Compare(x.Key, y.Key); if (keyCompare == 0) return valueComparer.Compare(x.Value, y.Value); else return keyCompare; } public override bool Equals(object obj) { if (obj is PairComparer) return object.Equals(keyComparer, ((PairComparer)obj).keyComparer) && object.Equals(valueComparer, ((PairComparer)obj).valueComparer); else return false; } public override int GetHashCode() { return keyComparer.GetHashCode() ^ valueComparer.GetHashCode(); } } /// /// Class to change an Comparison<T> to an IComparer<T>. /// [Serializable] class ComparisonComparer : IComparer { private Comparison comparison; public ComparisonComparer(Comparison comparison) { this.comparison = comparison; } public int Compare(T x, T y) { return comparison(x, y); } public override bool Equals(object obj) { if (obj is ComparisonComparer) return comparison.Equals(((ComparisonComparer)obj).comparison); else return false; } public override int GetHashCode() { return comparison.GetHashCode(); } } /// /// Class to change an Comparison<TKey> to an IComparer<KeyValuePair<TKey, TValue>>. /// GetHashCode cannot be used on this class. /// [Serializable] class ComparisonKeyValueComparer : IComparer> { private Comparison comparison; public ComparisonKeyValueComparer(Comparison comparison) { this.comparison = comparison; } public int Compare(KeyValuePair x, KeyValuePair y) { return comparison(x.Key, y.Key); } public override bool Equals(object obj) { if (obj is ComparisonKeyValueComparer) return comparison.Equals(((ComparisonKeyValueComparer)obj).comparison); else return false; } public override int GetHashCode() { return comparison.GetHashCode(); } } /// /// Given an Comparison on a type, returns an IComparer on that type. /// /// T to compare. /// Comparison delegate on T /// IComparer that uses the comparison. public static IComparer ComparerFromComparison(Comparison comparison) { if (comparison == null) throw new ArgumentNullException("comparison"); return new ComparisonComparer(comparison); } /// /// Given an IComparer on TKey, returns an IComparer on /// key-value Pairs. /// /// TKey of the pairs /// TValue of the apris /// IComparer on TKey /// IComparer for comparing key-value pairs. public static IComparer> ComparerKeyValueFromComparerKey(IComparer keyComparer) { if (keyComparer == null) throw new ArgumentNullException("keyComparer"); return new KeyValueComparer(keyComparer); } /// /// Given an IEqualityComparer on TKey, returns an IEqualityComparer on /// key-value Pairs. /// /// TKey of the pairs /// TValue of the apris /// IComparer on TKey /// IEqualityComparer for comparing key-value pairs. public static IEqualityComparer> EqualityComparerKeyValueFromComparerKey(IEqualityComparer keyEqualityComparer) { if (keyEqualityComparer == null) throw new ArgumentNullException("keyEqualityComparer"); return new KeyValueEqualityComparer(keyEqualityComparer); } /// /// Given an IComparer on TKey and TValue, returns an IComparer on /// key-value Pairs of TKey and TValue, comparing first keys, then values. /// /// TKey of the pairs /// TValue of the apris /// IComparer on TKey /// IComparer on TValue /// IComparer for comparing key-value pairs. public static IComparer> ComparerPairFromKeyValueComparers(IComparer keyComparer, IComparer valueComparer) { if (keyComparer == null) throw new ArgumentNullException("keyComparer"); if (valueComparer == null) throw new ArgumentNullException("valueComparer"); return new PairComparer(keyComparer, valueComparer); } /// /// Given an Comparison on TKey, returns an IComparer on /// key-value Pairs. /// /// TKey of the pairs /// TValue of the apris /// Comparison delegate on TKey /// IComparer for comparing key-value pairs. public static IComparer> ComparerKeyValueFromComparisonKey(Comparison keyComparison) { if (keyComparison == null) throw new ArgumentNullException("keyComparison"); return new ComparisonKeyValueComparer(keyComparison); } /// /// Given an element type, check that it implements IComparable<T> or IComparable, then returns /// a IComparer that can be used to compare elements of that type. /// /// The IComparer<T> instance. /// T does not implement IComparable<T>. public static IComparer DefaultComparer() { if (typeof(IComparable).IsAssignableFrom(typeof(T)) || typeof(System.IComparable).IsAssignableFrom(typeof(T))) { return Comparer.Default; } else { throw new InvalidOperationException(string.Format(Strings.UncomparableType, typeof(T).FullName)); } } /// /// Given an key and value type, check that TKey implements IComparable<T> or IComparable, then returns /// a IComparer that can be used to compare KeyValuePairs of those types. /// /// The IComparer<KeyValuePair<TKey, TValue>> instance. /// TKey does not implement IComparable<T>. public static IComparer> DefaultKeyValueComparer() { IComparer keyComparer = DefaultComparer(); return ComparerKeyValueFromComparerKey(keyComparer); } } }