/// <summary> /// 确定指定的两个数组 <see cref="Array"/> 的所有元素的值是否递归相等。 /// </summary> /// <param name="value">要进行值相等比较的第一个数组。</param> /// <param name="other">要进行值相等比较的第二个数组。</param> /// <param name="compared">当前已经比较过的对象的键值对。</param> /// <returns>若 <paramref name="value"/> 和 <paramref name="other"/> /// 均为数组 <see cref="Array"/>,且类型和尺寸相同,每个元素的值递归相等, /// 则为 <see langword="true"/>,否则为 <see langword="false"/>。</returns> private static bool ArrayRecursiveEquals( Array value, Array other, HashSet <ObjectPair> compared) { if (value.Rank != other.Rank) { return(false); } if (value.Length != other.Length) { return(false); } for (int rank = 0; rank < value.Rank; rank++) { if (value.GetLength(rank) != other.GetLength(rank)) { return(false); } } var typeArray = value.GetType(); if (typeArray.GetElementType() !.IsPointer) { var methodGet = typeArray.GetMethod("Get") !; for (int index = 0; index < value.Length; index++) { var valueItem = methodGet.Invoke(value, value.OffsetToIndices(index).Box()) !; var otherItem = methodGet.Invoke(other, other.OffsetToIndices(index).Box()) !; if (!ObjectRuntimeValue.BoxedPointerEquals(valueItem, otherItem)) { return(false); } } }
/// <summary> /// 确定指定的两个对象包含的值是否递归相等。 /// </summary> /// <remarks>基于反射调用,可能存在性能问题。</remarks> /// <param name="value">要进行值相等比较的第一个对象。</param> /// <param name="other">要进行值相等比较的第二个对象。</param> /// <returns>若 <paramref name="value"/> 与 <paramref name="other"/> 包含的值递归相等, /// 则为 <see langword="true"/>;否则为 <see langword="false"/>。</returns> /// <exception cref="MemberAccessException">调用方没有权限来访问对象的成员。</exception> public static bool RecursiveEquals(object?value, object?other) { var comparer = PairReferenceEqualityComparer.Default; var compared = new HashSet <ObjectPair>(comparer); return(ObjectRuntimeValue.RecursiveEquals(value, other, compared)); }
/// <summary> /// 获取指定对象递归包含的值的哈希代码。 /// </summary> /// <remarks>基于反射调用,可能存在性能问题。</remarks> /// <param name="value">要获取递归包含的值的哈希代码的对象。</param> /// <returns><paramref name="value"/> 递归包含的值的哈希代码。</returns> /// <exception cref="MemberAccessException">调用方没有权限来访问对象的成员。</exception> public static int GetRecursiveHashCode(object?value) { var comparer = ReferenceEqualityComparer.Default; var computed = new HashSet <object>(comparer); return(ObjectRuntimeValue.GetRecursiveHashCode(value, computed)); }
/// <summary> /// 获取指定对象递归包含的值的哈希代码。 /// </summary> /// <param name="value">要获取基于值的哈希代码的对象。</param> /// <param name="computed">已经计算过哈希代码的对象。</param> /// <returns><paramref name="value"/> 递归包含的值的哈希代码。</returns> /// <exception cref="MemberAccessException">调用方没有权限来访问对象的成员。</exception> private static int GetRecursiveHashCode(object?value, HashSet <object> computed) { if (value is null) { return(0); } if (!computed.Add(value)) { return(0); } var type = value.GetType(); if (type.IsPrimitive) { return(ObjectRuntimeValue.GetPrimitiveHashCode(value)); } if (type == typeof(string)) { return(ObjectRuntimeValue.GetPrimitiveHashCode(value)); } else if (type.IsArray) { return(ObjectRuntimeValue.GetArrayRecursiveHashCode((Array)value, computed)); } else { return(ObjectRuntimeValue.GetObjectRecursiveHashCode(value, computed)); } }
/// <summary> /// 获取指定数组中所有元素的递归包含的值的哈希代码。 /// </summary> /// <param name="value">要获取基于值的哈希代码的数组。</param> /// <param name="computed">已经计算过哈希代码的对象。</param> /// <returns><paramref name="value"/> 中所有元素的递归包含的值的哈希代码。</returns> /// <exception cref="MemberAccessException">调用方没有权限来访问对象的成员。</exception> private static int GetArrayRecursiveHashCode(Array value, HashSet <object> computed) { var hashCode = value.GetType().GetHashCode(); var typeArray = value.GetType(); if (typeArray.GetElementType() !.IsPointer) { var methodGet = typeArray.GetMethod("Get") !; for (int index = 0; index < value.Length; index++) { var item = methodGet.Invoke(value, value.OffsetToIndices(index).Box()) !; hashCode = ObjectRuntimeValue.CombineHashCode( hashCode, ObjectRuntimeValue.GetBoxedPointerHashCode(item)); } }
/// <summary> /// 确定指定的两个对象包含的值是否递归相等。 /// </summary> /// <param name="value">要进行值相等比较的第一个对象。</param> /// <param name="other">要进行值相等比较的第二个对象。</param> /// <param name="compared">当前已经比较过的对象的键值对。</param> /// <returns>若 <paramref name="value"/> 与 <paramref name="other"/> 包含的值递归相等, /// 则为 <see langword="true"/>;否则为 <see langword="false"/>。</returns> /// <exception cref="MemberAccessException">调用方没有权限来访问对象的成员。</exception> private static bool RecursiveEquals( object?value, object?other, HashSet <ObjectPair> compared) { if (RuntimeHelpers.Equals(value, other)) { return(true); } if ((value is null) || (other is null)) { return(false); } if (value.GetType() != other.GetType()) { return(false); } var pair = new ObjectPair(value, other); if (!compared.Add(pair)) { return(true); } var type = value.GetType(); if (type.IsPrimitive) { return(ObjectRuntimeValue.PrimitiveEquals(value, other)); } if (type == typeof(string)) { return(ObjectRuntimeValue.PrimitiveEquals(value, other)); } else if (type.IsArray) { return(ObjectRuntimeValue.ArrayRecursiveEquals((Array)value, (Array)other, compared)); } else { return(ObjectRuntimeValue.ObjectRecursiveEquals(value, other, compared)); } }
/// <summary> /// 确定当前对象与指定对象的值是否相等。 /// </summary> /// <remarks>基于反射调用,可能存在性能问题。 /// 将递归比较至对象的字段(数组的元素)为 .NET 基元类型 (<see cref="Type.IsPrimitive"/>)、 /// 字符串 <see cref="string"/> 或指针类型 (<see cref="Type.IsPointer"/>)。</remarks> /// <typeparam name="T">对象的类型。</typeparam> /// <param name="value">要进行值相等比较的对象。</param> /// <param name="other">要与当前对象进行比较的对象。</param> /// <returns>若 <paramref name="value"/> 与 <paramref name="other"/> 的值相等, /// 则为 <see langword="true"/>;否则为 <see langword="false"/>。</returns> public static bool ValueEquals <T>(this T?value, T?other) => ObjectRuntimeValue.RecursiveEquals(value, other);
public static T?SerializationClone <T>(this T?value) => (T?)ObjectRuntimeValue.SerializationClone(value);
public static T?RecursiveClone <T>(this T?value) => (T?)ObjectRuntimeValue.RecursiveClone(value);
public static T?DirectClone <T>(this T?value) => (T?)ObjectRuntimeValue.DirectClone(value);