in src/TestFramework/Extension.Desktop/RuntimeTypeHelper.cs [316:425]
internal static int FindMostSpecific(
ParameterInfo[] p1,
int[] paramOrder1,
Type paramArrayType1,
ParameterInfo[] p2,
int[] paramOrder2,
Type paramArrayType2,
Type[] types,
object[] args)
{
// A method using params is always less specific than one not using params
if (paramArrayType1 != null && paramArrayType2 == null)
{
return 2;
}
if (paramArrayType2 != null && paramArrayType1 == null)
{
return 1;
}
bool p1Less = false;
bool p2Less = false;
for (int i = 0; i < types.Length; i++)
{
if (args != null && args[i] == Type.Missing)
{
continue;
}
Type c1, c2;
// If a param array is present, then either
// the user re-ordered the parameters in which case
// the argument to the param array is either an array
// in which case the params is conceptually ignored and so paramArrayType1 == null
// or the argument to the param array is a single element
// in which case paramOrder[i] == p1.Length - 1 for that element
// or the user did not re-order the parameters in which case
// the paramOrder array could contain indexes larger than p.Length - 1
//// so any index >= p.Length - 1 is being put in the param array
if (paramArrayType1 != null && paramOrder1[i] >= p1.Length - 1)
{
c1 = paramArrayType1;
}
else
{
c1 = p1[paramOrder1[i]].ParameterType;
}
if (paramArrayType2 != null && paramOrder2[i] >= p2.Length - 1)
{
c2 = paramArrayType2;
}
else
{
c2 = p2[paramOrder2[i]].ParameterType;
}
if (c1 == c2)
{
continue;
}
if (c1.ContainsGenericParameters || c2.ContainsGenericParameters)
{
continue;
}
switch (FindMostSpecificType(c1, c2, types[i]))
{
case 0:
return 0;
case 1:
p1Less = true;
break;
case 2:
p2Less = true;
break;
}
}
// Two way p1Less and p2Less can be equal. All the arguments are the
// same they both equal false, otherwise there were things that both
// were the most specific type on....
if (p1Less == p2Less)
{
// it's possible that the 2 methods have same sig and default param in which case we match the one
// with the same number of args but only if they were exactly the same (that is p1Less and p2Lees are both false)
if (!p1Less && p1.Length != p2.Length && args != null)
{
if (p1.Length == args.Length)
{
return 1;
}
else if (p2.Length == args.Length)
{
return 2;
}
}
return 0;
}
else
{
return (p1Less == true) ? 1 : 2;
}
}