简体   繁体   English

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

[英]Why is the compiler choosing the wrong method overload?

I have this simple method: 我有这个简单的方法:

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.");
    }
}

The method above resolves the type of the memberInfo and calls the applicable method from the following: 上面的方法解析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...
}

The problem is that the last case label, case MemberTypes.Method, doesn't call the CacheDelegate method with the Method Info overload, but calls the CacheDelegate with the Member Info overload instead! 问题在于最后一个案例标签case MemberTypes.Method不会通过Method Info重载调用CacheDelegate方法,而是通过Member Info重载来调用CacheDelegate! So it's basically just calling itself over and over again, recursively. 因此,它基本上只是一次又一次地递归调用自己。 I tried specifying the parameter name, methodInfo: methodInfo when calling the method, but then the Unity engine is telling me the best overloaded method does not contain a parameter named methodInfo. 我尝试在调用方法时指定参数名称methodInfo:methodInfo,但是Unity引擎告诉我最好的重载方法不包含名为methodInfo的参数。

I'm quite at a loss of why this is happening. 我完全不知道为什么会这样。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Overload resolution works as follows. 重载解析的工作方式如下。

Starting with the type called on, find the set of methods declared on that type that can be used. 从调用的类型开始,找到可以使用的在该类型上声明的方法集。

If that set is empty, then try the same with the base type or interfaces declared. 如果该集合为空,则尝试对声明的基本类型或接口进行相同的操作。 Keep moving up the hierarchy until at least one method that matches is found, or else error. 继续向上移动层次结构,直到找到至少一种匹配的方法,否则将出错。

Of the set that is found, use the most specific method. 在找到的集合中,使用最特定的方法。 Error if it's a tie. 如果是平局则出错。

So, of the four methods, three were declared in this class. 因此,在这四个方法中,有三个在此类中声明。 Of those three two are not applicable. 这三个中的两个不适用。 That leaves only public void CacheDelegate(Object obj, MemberInfo memberInfo) as clearly the correct class to call, so it is called. 显然public void CacheDelegate(Object obj, MemberInfo memberInfo)只有public void CacheDelegate(Object obj, MemberInfo memberInfo)作为正确的正确类来调用,因此可以调用它。

You could use ((BaseType)this).CacheDelegate(obj, methodInfo); 您可以使用((BaseType)this).CacheDelegate(obj, methodInfo); to force the call you want, since the base type has only one CacheDelegate overload to choose between. 强制您要进行的呼叫,因为基本类型只有一个CacheDelegate重载可供选择。

Jon Hanna already explained why this is happening, I'll just add on by providing the source spec where you can read the details: https://msdn.microsoft.com/en-us/library/aa691336(v=vs.71).aspx 乔恩·汉纳(Jon Hanna)已经解释了为什么会发生这种情况,我将通过提供可阅读详细信息的源规范进行补充: https : //msdn.microsoft.com/zh-cn/library/aa691336(v=vs.71 )的.aspx

Here's a few ways you can solve your issue: 您可以通过以下几种方式解决问题:

  • Don't override or overload that method, use a different name. 不要覆盖或重载该方法,请使用其他名称。
  • Don't override that method, overload using different parameters, like adding object ignoreMe . 不要重写该方法,使用不同的参数进行重载,例如添加object ignoreMe This will force the overload to be compatible, however most will agree it's far from elegant. 这将迫使重载兼容,但是大多数人都认为它远非优雅。
  • Instead of overriding, hide the method using new . 而不是覆盖,而是使用new隐藏方法。 I'm not 100% sure how overload resolution works when method hiding is involved, but it should cause it to use the correct method. 我不确定100%涉及方法隐藏时重载解析的工作原理,但导致它使用正确的方法。 Keep in mind that doing this will of course remove it's polymorphism. 请记住,这样做当然会消除它的多态性。
  • Use reflection to manually find the correct overload, and invoke it. 使用反射手动找到正确的重载,然后调用它。 This is the messiest one, and also has the most overhead. 这是最乱的,而且开销最大。 This may or may not be a problem, depending on your situation. 根据您的具体情况,这可能是问题,也可能不是问题。 However it's the only solution that retains full polymorphism, if you really want to use that exact override / overload combo. 但是,如果您确实想使用该确切的覆盖/重载组合,则它是保留完整多态性的唯一解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM