return false;
}
+#if FEATURE_TYPEEQUIVALENCE
+ // Reflexive, symmetric, transitive.
+ public override bool IsEquivalentTo(Type other)
+ {
+ var otherRtType = other as RuntimeType;
+ if (otherRtType is null)
+ {
+ return false;
+ }
+
+ if (otherRtType == this)
+ {
+ return true;
+ }
+
+ return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType);
+ }
+#endif // FEATURE_TYPEEQUIVALENCE
+
public override Type BaseType => GetBaseType();
private RuntimeType GetBaseType()
{
throw new PlatformNotSupportedException();
}
+
+#if FEATURE_TYPEEQUIVALENCE
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsEquivalentTo(RuntimeType rtType1, RuntimeType rtType2);
+#endif // FEATURE_TYPEEQUIVALENCE
}
// This type is used to remove the expense of having a managed reference object that is dynamically
FCFuncElement("Allocate", RuntimeTypeHandle::Allocate) //for A.CI
FCFuncElement("CompareCanonicalHandles", RuntimeTypeHandle::CompareCanonicalHandles)
FCIntrinsic("GetValueInternal", RuntimeTypeHandle::GetValueInternal, CORINFO_INTRINSIC_RTH_GetValueInternal)
+ FCFuncElement("IsEquivalentTo", RuntimeTypeHandle::IsEquivalentTo)
FCFuncEnd()
FCFuncStart(gMetaDataImport)
}
FCIMPLEND
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF rtType1 = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(rtType1UNSAFE);
+ REFLECTCLASSBASEREF rtType2 = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(rtType2UNSAFE);
+
+ BOOL areEquivalent = FALSE;
+ HELPER_METHOD_FRAME_BEGIN_RET_2(rtType1, rtType2);
+
+ if (rtType1 != NULL && rtType2 != NULL)
+ areEquivalent = rtType1->GetType().IsEquivalentTo(rtType2->GetType());
+
+ HELPER_METHOD_FRAME_END();
+
+ FC_RETURN_BOOL(areEquivalent);
+}
+FCIMPLEND
+
// TypeEqualsHelper and TypeNotEqualsHelper are almost identical.
// Unfortunately we cannot combime them because they need to hardcode the caller's name
NOINLINE static BOOL TypeEqualSlow(OBJECTREF refL, OBJECTREF refR, LPVOID __me)
static FCDECL1_V(ReflectClassBaseObject*, GetTypeFromHandle, FCALLRuntimeTypeHandle th);
static FCDECL1_V(EnregisteredTypeHandle, GetValueInternal, FCALLRuntimeTypeHandle RTH);
+ static FCDECL2(FC_BOOL_RET, IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE);
+
static FCDECL2(FC_BOOL_RET, TypeEQ, Object* left, Object* right);
static FCDECL2(FC_BOOL_RET, TypeNEQ, Object* left, Object* right);
}
}
+ private static void ValidateTypeInstanceEquality()
+ {
+ Console.WriteLine($"{nameof(ValidateTypeInstanceEquality)}");
+ var inAsm = EmptyType.Create();
+ var otherAsm = EmptyType2.Create();
+
+ Type inAsmInterfaceType = inAsm.GetType().GetInterface(nameof(IEmptyType));
+ Type otherAsmInterfaceType = otherAsm.GetType().GetInterface(nameof(IEmptyType));
+
+ // Sanity checks
+ Assert.IsTrue(inAsmInterfaceType == inAsmInterfaceType);
+ Assert.IsTrue(inAsmInterfaceType.IsEquivalentTo(inAsmInterfaceType));
+ Assert.IsFalse(inAsmInterfaceType.IsEquivalentTo(inAsm.GetType()));
+ Assert.IsTrue(otherAsmInterfaceType == otherAsmInterfaceType);
+ Assert.IsTrue(otherAsmInterfaceType.IsEquivalentTo(otherAsmInterfaceType));
+ Assert.IsFalse(otherAsmInterfaceType.IsEquivalentTo(otherAsm.GetType()));
+
+ // The intrinsic equality operations should fail
+ Assert.IsFalse(inAsmInterfaceType == otherAsmInterfaceType);
+ Assert.IsFalse(inAsmInterfaceType.Equals(otherAsmInterfaceType));
+ Assert.IsFalse(otherAsmInterfaceType == inAsmInterfaceType);
+ Assert.IsFalse(otherAsmInterfaceType.Equals(inAsmInterfaceType));
+
+ // Determination of equal types requires API call
+ Assert.IsTrue(inAsmInterfaceType.IsEquivalentTo(otherAsmInterfaceType));
+ Assert.IsTrue(otherAsmInterfaceType.IsEquivalentTo(inAsmInterfaceType));
+ }
+
private class MethodTestDerived : MethodTestBase
{
private readonly int scaleValue;
try
{
InterfaceTypesFromDifferentAssembliesAreEquivalent();
+ ValidateTypeInstanceEquality();
InterfaceTypesMethodOperations();
CallSparseInterface();
}
return 100;
}
-}
\ No newline at end of file
+}