return FindMatchingVirtualMethodOnTypeByNameAndSig(method, currentType, reverseMethodSearch, nameSigMatchMethodIsValidCandidate: s_VerifyMethodsHaveTheSameVirtualSlot);
}
- private static Func<MethodDesc, MethodDesc, bool> s_VerifyMethodsHaveTheSameVirtualSlot = VerifyMethodsHaveTheSameVirtualSlot;
+ private static readonly Func<MethodDesc, MethodDesc, bool> s_VerifyMethodsHaveTheSameVirtualSlot = VerifyMethodsHaveTheSameVirtualSlot;
// Return true if the slot that defines methodToVerify matches slotDefiningMethod
private static bool VerifyMethodsHaveTheSameVirtualSlot(MethodDesc slotDefiningMethod, MethodDesc methodToVerify)
return slotDefiningMethodOfMethodToVerify == slotDefiningMethod;
}
+ private static readonly Func<MethodDesc, MethodDesc, bool> s_VerifyMethodIsPublic = VerifyMethodIsPublic;
+
+ // Return true if the method to verify is public
+ private static bool VerifyMethodIsPublic(MethodDesc slotDefiningMethod, MethodDesc methodToVerify)
+ {
+ return methodToVerify.IsPublic;
+ }
+
private static void FindBaseUnificationGroup(MetadataType currentType, UnificationGroup unificationGroup)
{
MethodDesc originalDefiningMethod = unificationGroup.DefiningMethod;
{
MethodDesc foundOnCurrentType = FindMatchingVirtualMethodOnTypeByNameAndSig(interfaceMethod, currentType,
reverseMethodSearch: false, /* When searching for name/sig overrides on a type that explicitly defines an interface, search through the type in the forward direction*/
- nameSigMatchMethodIsValidCandidate :null);
+ nameSigMatchMethodIsValidCandidate: s_VerifyMethodIsPublic);
foundOnCurrentType = FindSlotDefiningMethodForVirtualMethod(foundOnCurrentType);
if (baseType == null)
{
MethodDesc foundOnCurrentType = FindMatchingVirtualMethodOnTypeByNameAndSig(interfaceMethod, currentType,
reverseMethodSearch: false, /* When searching for name/sig overrides on a type that is the first type in the hierarchy to require the interface, search through the type in the forward direction*/
- nameSigMatchMethodIsValidCandidate: null);
+ nameSigMatchMethodIsValidCandidate: s_VerifyMethodIsPublic);
foundOnCurrentType = FindSlotDefiningMethodForVirtualMethod(foundOnCurrentType);
MethodDesc nameSigOverride = FindMatchingVirtualMethodOnTypeByNameAndSig(interfaceMethod, currentType,
reverseMethodSearch: true, /* When searching for a name sig match for an interface on parent types search in reverse order of declaration */
- nameSigMatchMethodIsValidCandidate:null);
+ nameSigMatchMethodIsValidCandidate: s_VerifyMethodIsPublic);
if (nameSigOverride != null)
{
if (TestIterfaceCallOptimization() == Fail)
return Fail;
+ TestPublicAndNonpublicDifference.Run();
TestDefaultInterfaceMethods.Run();
TestDefaultInterfaceVariance.Run();
TestVariantInterfaceOptimizations.Run();
#endregion
+ class TestPublicAndNonpublicDifference
+ {
+ interface IFrobber
+ {
+ string Frob();
+ }
+ class ProtectedBase : IFrobber
+ {
+ string IFrobber.Frob() => "IFrobber.Frob";
+ protected virtual string Frob() => "Base.Frob";
+ }
+
+ class ProtectedDerived : ProtectedBase, IFrobber
+ {
+ protected override string Frob() => "Derived.Frob";
+ }
+
+ class PublicBase : IFrobber
+ {
+ string IFrobber.Frob() => "IFrobber.Frob";
+ public virtual string Frob() => "Base.Frob";
+ }
+
+ class PublicDerived : PublicBase, IFrobber
+ {
+ public override string Frob() => "Derived.Frob";
+ }
+
+ public static void Run()
+ {
+ IFrobber f1 = new PublicDerived();
+ if (f1.Frob() != "Derived.Frob")
+ throw new Exception();
+
+ IFrobber f2 = new ProtectedDerived();
+ if (f2.Frob() != "IFrobber.Frob")
+ throw new Exception();
+ }
+ }
+
class TestDefaultInterfaceMethods
{
interface IFoo