为什么编译器选择错误的方法重载?
我有这个简单的方法:
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手动查找正确的重载,并调用它。 这是最混乱的,也是最开销的。 根据您的具体情况,这可能是也可能不是问题。 但是,如果你真的想要使用那个精确的覆盖/重载组合,它是唯一保留完全多态性的解决方案。