为什么编译器选择了错误的方法重载
本文关键字:方法 重载 错误 编译器 选择 为什么 | 更新日期: 2023-09-27 18:32:46
我有一个简单的方法:
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 不会使用方法信息重载调用 CacheDelegate 方法,而是使用成员信息重载调用 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% 确定重载解决方案是如何工作的,但它应该导致它使用正确的方法。请记住,这样做当然会消除它的多态性。 - 使用反射手动查找正确的重载,并调用它。这是最混乱的一个,也是开销最大的。这可能是也可能不是问题,具体取决于您的情况。但是,如果您真的想使用确切的覆盖/重载组合,它是唯一保留完全多态性的解决方案。