为什么编译器选择错误的方法重载?

我有这个简单的方法:

public void CacheDelegate(Object obj, MemberInfo memberInfo) { switch (memberInfo.MemberType) { case MemberTypes.Field: var fieldInfo = (FieldInfo) memberInfo; CacheDelegate(obj, fieldInfo); break; case MemberTypes.Property: var propertyInfo = (PropertyInfo) memberInfo; CacheDelegate(obj, propertyInfo); break; case MemberTypes.Method: var methodInfo = (MethodInfo) memberInfo; CacheDelegate(obj, methodInfo); break; default: throw new Exception("Cannot create a delegate for MemberInfo provided."); } } 

上面的方法解析了memberInfo的类型,并从以下方法调用适用的方法:

 public void CacheDelegate(Object obj, FieldInfo fieldInfo) { // Do stuff... } public void CacheDelegate(Object obj, PropertyInfo propertyInfo) { // Do stuff... } public sealed override void CacheDelegate(Object obj, MethodInfo methodInfo) { // Do stuff... } 

问题是最后一个case标签,例如MemberTypes.Method,没有使用Method Info重载调用CacheDelegate方法,而是调用带有Member Info重载的CacheDelegate! 所以它基本上只是一遍又一遍地反复呼唤自己。 我在调用方法时尝试指定参数名称methodInfo:methodInfo,但Unity引擎告诉我最好的重载方法不包含名为methodInfo的参数。

我完全不知道为什么会发生这种情况。 任何帮助将不胜感激。

过载分辨率的工作原理如下。

从名为on的类型开始,找到在该类型上声明的可以使用的方法集。

如果该集合为空,则尝试使用所声明的基本类型或接口。 继续向上移动层次结构,直到找到至少一个匹配的方法,否则出错。

在找到的集合中,使用最具体的方法。 错误,如果它是一个平局。

因此,在这四种方法中,有三种是在这个类中声明的。 其中三个不适用。 只留下public void CacheDelegate(Object obj, MemberInfo memberInfo)作为要调用的正确类,因此调用它。

你可以使用((BaseType)this).CacheDelegate(obj, methodInfo); 强制执行所需的调用,因为基类型只有一个CacheDelegate重载可供选择。

Jon Hanna已经解释了为什么会发生这种情况,我将通过提供您可以阅读详细信息的源规范来添加: https : //msdn.microsoft.com/en-us/library/aa691336(v = vs.71 )的.aspx

您可以通过以下几种方式解决问题:

  • 不要覆盖或重载该方法,使用其他名称。
  • 不要覆盖该方法,使用不同的参数进行重载,例如添加object ignoreMe 。 这将迫使过载兼容,但大多数人会认为它远非优雅。
  • 而不是覆盖,使用new隐藏方法。 我不是100%确定在涉及方法隐藏时重载解析如何工作,但它应该使它使用正确的方法。 请记住,这样做当然会删除它的多态性。
  • 使用reflection手动查找正确的重载,并调用它。 这是最混乱的,也是最开销的。 根据您的具体情况,这可能是也可能不是问题。 但是,如果你真的想要使用那个精确的覆盖/重载组合,它是唯一保留完全多态性的解决方案。