public static bool IsEqualTo(this IElementNavigator left, IElementNavigator right) { var l = left.Value; var r = right.Value; // Compare primitives (or extended primitives) if (l != null && r != null) { if (l.GetType() == typeof(string) && r.GetType() == typeof(string)) { return((string)l == (string)r); } else if (l.GetType() == typeof(bool) && r.GetType() == typeof(bool)) { return((bool)l == (bool)r); } else if (l.GetType() == typeof(long) && r.GetType() == typeof(long)) { return((long)l == (long)r); } else if (l.GetType() == typeof(decimal) && r.GetType() == typeof(decimal)) { return((decimal)l == (decimal)r); } else if (l.GetType() == typeof(long) && r.GetType() == typeof(decimal)) { return((decimal)(long)l == (decimal)r); } else if (l.GetType() == typeof(decimal) && r.GetType() == typeof(long)) { return((decimal)l == (decimal)(long)r); } else if (l.GetType() == typeof(PartialTime) && r.GetType() == typeof(PartialTime)) { return((PartialTime)l == (PartialTime)r); } else if (l.GetType() == typeof(PartialDateTime) && r.GetType() == typeof(PartialDateTime)) { return((PartialDateTime)l == (PartialDateTime)r); } else { return(false); } } else if (l == null && r == null) { // Compare complex types (extensions on primitives are not compared, but handled (=ignored) above var childrenL = left.childrenOrEmpty(); var childrenR = right.childrenOrEmpty(); bool allNamesAreEqual = childrenL.Zip(childrenR, (childL, childR) => namesAreEqual(childL, childR)).All(t => t); return(allNamesAreEqual && childrenL.IsEqualTo(childrenR)); // NOTE: Assumes null will never be returned when any() children exist } else { // Else, we're comparing a complex (without a value) to a primitive which (probably) should return false return(false); } }