/// <summary> /// Gets the hashcode of a single object. If the object is an enumerable it will make a hashcode of the enumeration. /// </summary> /// <param name="o">Object to make the hashcode for.</param> /// <returns>A hashcode.</returns> public static int GetHashCodeForSingleObject(object o) { if (ReferenceEquals(o, null)) { return(0); } var oEnumerable = o as IEnumerable; if (oEnumerable == null) { // check for the special case of KeyValuePair (items of a dictionary) var kvp = KeyValuePairMethods.TryExtractKeyValuePair(o); if (kvp != null) { return(GetHashCodeFor(kvp.Item1, kvp.Item2)); } return(o.GetHashCode()); } // make a hash of the items if it is an enumerable var oEnum = oEnumerable.GetEnumerator(); var list = new List <object>(); while (oEnum.MoveNext()) { list.Add(oEnum.Current); } return(GetHashCodeFor(list.ToArray())); }
public static KeyValuePairMethods GetForType(Type type) { if (!type.IsGenericType || (StripGenericFromFullName(type.FullName) != ClassFullName)) { return(null); } // TODO: this probably could be more performant by using a concurrent dictionary lock (KeyValuePairMethodsDictionaryLock) { KeyValuePairMethods kvpm; if (!KeyValuePairMethodsDictionary.TryGetValue(type, out kvpm)) { kvpm = new KeyValuePairMethods(type); KeyValuePairMethodsDictionary.Add(type, kvpm); } return(kvpm); } }
/// <summary> /// Returns the string representation of an object, null if null or [items] if a collection. /// </summary> /// <param name="o"></param> /// <returns>The string representation.</returns> public static string ToStringForSingleObject(object o) { if (ReferenceEquals(o, null)) { return("null"); } var oEnumerable = o as IEnumerable; if (oEnumerable == null) { // check for the special case of KeyValuePair (items of a dictionary) var kvp = KeyValuePairMethods.TryExtractKeyValuePair(o); if (kvp != null) { return("(" + ToStringForSingleObject(kvp.Item1) + ", " + ToStringForSingleObject(kvp.Item2) + ")"); } return(o.ToString()); } // make a list of the items if it is an enumerable var oEnum = oEnumerable.GetEnumerator(); var list = new List <object>(); while (oEnum.MoveNext()) { list.Add(oEnum.Current); } var sb = new StringBuilder(); sb.Append("[ "); // TODO: this could be optimized by not using select and using the append on each object instead sb.Append(string.Join(", ", list.Select(ToStringForSingleObject))); sb.Append(" ]"); return(sb.ToString()); }
/// <summary> /// Check if two objects are equal. /// </summary> /// <typeparam name="T">Object type.</typeparam> /// <param name="a">First object.</param> /// <param name="b">Second object.</param> /// <returns>true if they are equal, false otherwise.</returns> public static bool AreEqual <T>(T a, T b) { bool aIsNull = ReferenceEquals(a, null), bIsNull = ReferenceEquals(b, null); if (aIsNull && bIsNull) { return(true); } if (aIsNull || bIsNull) { return(false); } var equals = a.Equals(b); if (equals) { return(true); } // check for the special case of KeyValuePair (items of a dictionary) var aKvp = KeyValuePairMethods.TryExtractKeyValuePair(a); if (aKvp != null) { var bKvp = KeyValuePairMethods.TryExtractKeyValuePair(b); return(AreEqual(aKvp.Item1, bKvp.Item1) && AreEqual(aKvp.Item2, bKvp.Item2)); } // one extra check for enumerables // first a fastcheck for collection size var aCollection = a as ICollection; var bCollection = b as ICollection; if ((aCollection != null) && (bCollection != null)) { if (aCollection.Count != bCollection.Count) { return(false); } } var aEnumerable = a as IEnumerable; var bEnumerable = b as IEnumerable; if ((aEnumerable == null) || (bEnumerable == null)) { return(false); } var aEnum = aEnumerable.GetEnumerator(); var bEnum = bEnumerable.GetEnumerator(); while (aEnum.MoveNext()) { if (!bEnum.MoveNext()) { return(false); } object aCurrent = aEnum.Current, bCurrent = bEnum.Current; if (!AreEqual(aCurrent, bCurrent)) { return(false); } } // all items so far are the same, but does b have one more? return(!bEnum.MoveNext()); }