/// <summary> /// Checks if two types are compatible according to compatible-with as described in ECMA 335 I.8.7.1 /// Most of the checks are performed by the CanCastTo, but some cases are pre-filtered out. /// </summary> public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType) { // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1 bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType; if (isCastFromValueTypeToReferenceType) { return(false); } // Managed pointers are compatible only if they are pointer-element-compatible-with as described in ECMA I.8.7.2 if (thisType.IsByRef && otherType.IsByRef) { return(AreVerificationTypesEqual(thisType.GetParameterType(), otherType.GetParameterType())); } // Unmanaged pointers are handled the same way as managed pointers if (thisType.IsPointer && otherType.IsPointer) { return(AreVerificationTypesEqual(thisType.GetParameterType(), otherType.GetParameterType())); } // Function pointers are compatible only if they are method-signature-compatible-with as described in ECMA I.8.7.1 if (thisType.IsFunctionPointer && otherType.IsFunctionPointer) { return(IsMethodSignatureCompatibleWith(thisType, otherType)); } // None of the types can be a managed pointer, a pointer or a function pointer here, // all the valid cases were handled above. if (thisType.IsByRef || otherType.IsByRef || thisType.IsPointer || otherType.IsPointer || thisType.IsFunctionPointer || otherType.IsFunctionPointer) { return(false); } // Nullable<T> can be cast to T, but this is not compatible according to ECMA I.8.7.1 bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]); if (isCastFromNullableOfTtoT) { return(false); } return(otherType.CanCastTo(thisType)); }
public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType) { // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1 bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType; if (isCastFromValueTypeToReferenceType) { return(false); } // Nullable<T> can be cast to T, but this is not compatible according to ECMA I.8.7.1 bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]); if (isCastFromNullableOfTtoT) { return(false); } return(otherType.CanCastTo(thisType)); }