atl*_*ste 5 .net c# overload-resolution
假设我有一个如下课程:
public class AcceptMethods
{
public int Accept(string s, int k = 1)
{
return 1;
}
public int Accept(object s)
{
return 2;
}
public int Accept(IEnumerable<object> s)
{
return 7;
}
public int Accept(IList<object> s)
{
return 4;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我尝试在代码中使用它,我将使用如下代码:
object[] list = new object[] { "a", new object[0], "c", "d" };
Assert.AreEqual(7, list.Select((a)=>((int)new AcceptMethods().Accept((dynamic)a))).Sum());
Run Code Online (Sandbox Code Playgroud)
究其原因,它的7,是因为重载喜欢[ IList<object>]在[ IEnumerable<object>]和[ object],因为[ string,int=default]具有优先于[ object]。
在我的场景中,我想使用反射获得最佳的匹配重载。换句话说:“最佳”定义为“ c#重载分辨率”。例如:
int sum = 0;
foreach (var item in list)
{
var method = GetBestMatching(typeof(AcceptMethods).GetMethods(), item.GetType());
sum += (int)method.Invoke(myObject, new object[]{item});
}
Assert.AreEqual(7, sum);
Run Code Online (Sandbox Code Playgroud)
虽然我绘制的场景只有一个参数,但我寻求的解决方案却可以有多个参数。
更新1:
因为我收到一条评论,即由于过载解决方案实现的困难(我很清楚),所以这对于SO来说太困难了,因此我倾向于发送更新。为了使我的论点更有力,这是我的第一次尝试,它使用默认的.NET绑定程序来处理重载解析:
private MethodBase GetBestMatching(IEnumerable<MethodInfo> methods, Type[] parameters)
{
return Type.DefaultBinder.SelectMethod(BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
methods.ToArray(), parameters, null);
}
Run Code Online (Sandbox Code Playgroud)
这个版本似乎已经可以正确地执行简单的重载解析,但是无法使用可选参数。因为.NET afaik可以像我在此处显示的那样使用类型绑定,所以我认为该解决方案可以很容易地实现。
这是一个庞大的主题,需要大量的工作,在我看来,当然不能用这样的答案来概括。我建议您仔细阅读 C# 规范并阅读定义重载解析的正式规则(另外,请注意泛型方法),并尝试实现它们以满足您的需求。
更新
可选(即具有默认值的参数)并不是一个简单的情况 - 并且反射绑定器根本不尝试填充它们 - 这是因为编译器的工作是识别默认值,将它们拉出并将它们注入到对这样的方法。
您需要一种类似这样的多遍方法(注意 - 不包括泛型):
手动搜索参数数量和参数类型与您拥有的参数数量和类型完全匹配的方法。如果您找到匹配的物品,请使用它并下铺。
现在确定您的重载选择的方法的“候选列表”(通常是按名称 - 您也可以在此处排除泛型 - 除非您也打算尝试绑定它们)。
如果这些方法都没有可选参数,那么您可以继续根据您的问题使用默认绑定器来查找匹配项(如果没有,您需要一个基于类型的参数/参数排名算法 - 如果是这样,跳至 5)。
重新运行第 3 步中构建的候选列表,取出所有可选参数并将它们的默认值合并到您自己的参数列表中(此时您可能需要为每个方法构建一组单独的参数,包括您所使用的参数)已提供,但也是默认值)。
对 3) 和可能的 4) 中内置的这些方法运行排名算法来识别最佳匹配(您似乎对此有很好的处理,所以我不会在这里详细介绍所有内容 - 这不是一个简单的算法,我坦率地说,我也不能在这里逐字引用它!)。
您的排名算法应该产生明确的获胜方法 - 即具有独特的高分或类似分数。如果您分出明确的获胜者,那么这就是您的绑定者。否则你就会有歧义,你就必须逃避。
您可能对我自己的 SO 感兴趣 -默认参数和反射:如果 ParameterInfo.IsOptional 那么 DefaultValue 总是可靠的吗?- 这应该可以帮助您识别具有默认参数的方法,以及如何将它们取出。
| 归档时间: |
|
| 查看次数: |
857 次 |
| 最近记录: |