/// <summary> /// Gets the hash code of a type /// </summary> /// <param name="a">Type</param> /// <returns></returns> public int GetHashCode(DmdType a) { if ((object)a == null) { return(0); } if (!IncrementRecursionCounter()) { return(0); } int hc = CompareCustomModifiers ? GetHashCode(a.GetCustomModifiers()) : 0; switch (a.TypeSignatureKind) { case DmdTypeSignatureKind.Type: hc ^= (object)a.DeclaringType == null ? HASHCODE_MAGIC_TYPE : HASHCODE_MAGIC_NESTED_TYPE; hc ^= MemberNameGetHashCode(a.MetadataName); hc ^= MemberNameGetHashCode(a.MetadataNamespace); hc ^= GetHashCode(a.DeclaringType); // Don't include the type scope in the hash since it can be one of Module, ModuleRef, AssemblyRef // and we could only hash the common denominator which isn't much at all. break; case DmdTypeSignatureKind.Pointer: hc ^= HASHCODE_MAGIC_ET_PTR ^ GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.ByRef: hc ^= HASHCODE_MAGIC_ET_BYREF ^ GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.SZArray: hc ^= HASHCODE_MAGIC_ET_SZARRAY ^ GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.TypeGenericParameter: hc ^= HASHCODE_MAGIC_ET_VAR ^ a.GenericParameterPosition; if (CompareGenericParameterDeclaringMember) { hc ^= GetHashCode(a.DeclaringType); } break; case DmdTypeSignatureKind.MethodGenericParameter: hc ^= HASHCODE_MAGIC_ET_MVAR ^ a.GenericParameterPosition; if (CompareGenericParameterDeclaringMember) { options &= ~DmdSigComparerOptions.CompareGenericParameterDeclaringMember; hc ^= GetHashCode(a.DeclaringMethod); options |= DmdSigComparerOptions.CompareGenericParameterDeclaringMember; } break; case DmdTypeSignatureKind.MDArray: hc ^= HASHCODE_MAGIC_ET_ARRAY; hc ^= a.GetArrayRank(); if (!IgnoreMultiDimensionalArrayLowerBoundsAndSizes) { hc ^= GetHashCode(a.GetArraySizes()); hc ^= GetHashCode(a.GetArrayLowerBounds()); } hc ^= GetHashCode(a.GetElementType()); break; case DmdTypeSignatureKind.GenericInstance: hc ^= HASHCODE_MAGIC_ET_GENERICINST; hc ^= GetHashCode(a.GetGenericTypeDefinition()); hc ^= GetHashCode(a.GetGenericArguments()); break; case DmdTypeSignatureKind.FunctionPointer: hc ^= HASHCODE_MAGIC_ET_FNPTR; hc ^= GetHashCode(a.GetFunctionPointerMethodSignature()); break; default: throw new InvalidOperationException(); } DecrementRecursionCounter(); return(hc); }
/// <summary> /// Constructor /// </summary> /// <param name="options">Options</param> public DmdSigComparer(DmdSigComparerOptions options) { this.options = options; recursionCounter = 0; }
/// <summary> /// Compares two types /// </summary> /// <param name="a">First type</param> /// <param name="b">Second type</param> /// <returns></returns> public bool Equals(DmdType a, DmdType b) { if ((object)a == b) { return(true); } if ((object)a == null || (object)b == null) { return(false); } if (!IncrementRecursionCounter()) { return(false); } bool result; var at = a.TypeSignatureKind; if (at != b.TypeSignatureKind) { result = false; } else if (CompareCustomModifiers && !Equals(a.GetCustomModifiers(), b.GetCustomModifiers())) { result = false; } else { switch (at) { case DmdTypeSignatureKind.Type: result = MemberNameEquals(a.MetadataName, b.MetadataName) && MemberNameEquals(a.MetadataNamespace, b.MetadataNamespace) && Equals(a.DeclaringType, b.DeclaringType); // Type scope only needs to be checked if it's a non-nested type if (result && !DontCompareTypeScope && (object)a.DeclaringType == null) { result = TypeScopeEquals(a, b); if (!result) { // One or both of the types could be exported types. We need to // resolve them and then compare again. var ra = a.ResolveNoThrow(); var rb = (object)ra == null ? null : b.ResolveNoThrow(); result = (object)ra != null && (object)rb != null && TypeScopeEquals(ra, rb); if (!result && CheckTypeEquivalence) { result = TIAHelper.Equivalent(ra, rb); } } } break; case DmdTypeSignatureKind.Pointer: case DmdTypeSignatureKind.ByRef: case DmdTypeSignatureKind.SZArray: result = Equals(a.GetElementType(), b.GetElementType()); break; case DmdTypeSignatureKind.TypeGenericParameter: result = a.GenericParameterPosition == b.GenericParameterPosition; if (result && CompareGenericParameterDeclaringMember) { result = Equals(a.DeclaringType, b.DeclaringType); } break; case DmdTypeSignatureKind.MethodGenericParameter: result = a.GenericParameterPosition == b.GenericParameterPosition; if (result && CompareGenericParameterDeclaringMember) { options &= ~DmdSigComparerOptions.CompareGenericParameterDeclaringMember; result = Equals(a.DeclaringMethod, b.DeclaringMethod); options |= DmdSigComparerOptions.CompareGenericParameterDeclaringMember; } break; case DmdTypeSignatureKind.MDArray: result = a.GetArrayRank() == b.GetArrayRank() && (IgnoreMultiDimensionalArrayLowerBoundsAndSizes || (Equals(a.GetArraySizes(), b.GetArraySizes()) && Equals(a.GetArrayLowerBounds(), b.GetArrayLowerBounds()))) && Equals(a.GetElementType(), b.GetElementType()); break; case DmdTypeSignatureKind.GenericInstance: result = Equals(a.GetGenericTypeDefinition(), b.GetGenericTypeDefinition()) && Equals(a.GetGenericArguments(), b.GetGenericArguments()); break; case DmdTypeSignatureKind.FunctionPointer: result = Equals(a.GetFunctionPointerMethodSignature(), b.GetFunctionPointerMethodSignature()); break; default: throw new InvalidOperationException(); } } DecrementRecursionCounter(); return(result); }
/// <summary> /// Constructor /// </summary> /// <param name="options">Options</param> public DmdMemberInfoEqualityComparer(DmdSigComparerOptions options) => this.options = options;