What is the algorithm used by the memberwise equality test in .NET structs? I would like to know this so that I can use it as the basis for my own algorithm.
I am trying
Here's my own attempt at this problem. It works, but I'm not convinced I've covered all the bases.
public class MemberwiseEqualityComparer : IEqualityComparer
{
public bool Equals(object x, object y)
{
// ----------------------------------------------------------------
// 1. If exactly one is null, return false.
// 2. If they are the same reference, then they must be equal by
// definition.
// 3. If the objects are both IEnumerable, return the result of
// comparing each item.
// 4. If the objects are equatable, return the result of comparing
// them.
// 5. If the objects are different types, return false.
// 6. Iterate over the public properties and compare them. If there
// is a pair that are not equal, return false.
// 7. Return true.
// ----------------------------------------------------------------
//
// 1. If exactly one is null, return false.
//
if (null == x ^ null == y) return false;
//
// 2. If they are the same reference, then they must be equal by
// definition.
//
if (object.ReferenceEquals(x, y)) return true;
//
// 3. If the objects are both IEnumerable, return the result of
// comparing each item.
// For collections, we want to compare the contents rather than
// the properties of the collection itself so we check if the
// classes are IEnumerable instances before we check to see that
// they are the same type.
//
if (x is IEnumerable && y is IEnumerable && false == x is string)
{
return contentsAreEqual((IEnumerable)x, (IEnumerable)y);
}
//
// 4. If the objects are equatable, return the result of comparing
// them.
// We are assuming that the type of X implements IEquatable<> of itself
// (see below) which is true for the numeric types and string.
// e.g.: public class TypeOfX : IEquatable { ... }
//
var xType = x.GetType();
var yType = y.GetType();
var equatableType = typeof(IEquatable<>).MakeGenericType(xType);
if (equatableType.IsAssignableFrom(xType)
&& xType.IsAssignableFrom(yType))
{
return equatablesAreEqual(equatableType, x, y);
}
//
// 5. If the objects are different types, return false.
//
if (xType != yType) return false;
//
// 6. Iterate over the public properties and compare them. If there
// is a pair that are not equal, return false.
//
if (false == propertiesAndFieldsAreEqual(x, y)) return false;
//
// 7. Return true.
//
return true;
}
public int GetHashCode(object obj)
{
return null != obj ? obj.GetHashCode() : 0;
}
private bool contentsAreEqual(IEnumerable enumX, IEnumerable enumY)
{
var enumOfObjX = enumX.OfType