简体   繁体   English

当我期望它选择非泛型方法时,方法重载选择泛型方法

[英]Method overload selecting generic method when I was expecting it to select non-generic method

Take the following code: 采取以下代码:

class BaseClassA { }
class DerivedClassA1 : BaseClassA { }

class BaseClassB { }
class DerivedClassB1 : BaseClassB { }

static class Operations
{
    public static BaseClassA Method(BaseClassA baseA)
    {
        //...
        return baseA;
    }

    public static TBaseClassB Method<TBaseClassB>(TBaseClassB baseB)
        where TBaseClassB : BaseClassB, new()
    {
        //...
        return baseB;
    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClassA baseA = new BaseClassA();
            DerivedClassA1 derivedA1 = new DerivedClassA1();
            DerivedClassB1 derivedB1 = new DerivedClassB1();

            baseA = Operations.Method(baseA);
            derivedA1 = Operations.Method(derivedA1); // Compilation error
            derivedB1 = Operations.Method(derivedB1);
        }
    }
}

The line marked // Compilation error results in the following error: 标记为// Compilation error的行将导致以下错误:

The type 'DerivedClassA1' cannot be used as type parameter
'TBaseClassB' in the generic type or method
'Operations.Method<TBaseClassB>(TBaseClassB)'.
There is no implicit reference conversion from 'DerivedClassA1'
to 'BaseClassB'.

It appears that method overloading is selecting the Operations.Method<TBaseClassB>(TBaseClassB) method overload as opposed to the Operations.Method(BaseClassA) when given an argument of type DerivedClassA1 , which is contrary to what I would expect. 当给定类型为DerivedClassA1的参数时,方法重载似乎是选择Operations.Method<TBaseClassB>(TBaseClassB)方法重载,而不是Operations.Method(BaseClassA) ,这与我的预期相反。 Why is this? 为什么是这样? Am I doing something wrong? 难道我做错了什么? Is there a alternative/correct way of achieving what I want, which is to call the Method(BaseClassA) method overload. 有没有一种替代/正确的方法来实现我想要的,那就是调用Method(BaseClassA)方法重载。

Note that the example code is a simplified equivalent of some real code I'm working on. 请注意,示例代码是我正在处理的某些实际代码的简化等效项。 Apologies if the example looks contrived. 抱歉,如果该示例看起来人为。

Overload resolution doesn't take generic constraints into account, because these constraints are not really part of the method signature (you can't create identical methods in the same class where only the generic constraints are different). 重载解析不会考虑泛型约束,因为这些约束实际上并不是方法签名的一部分(您不能在只有泛型约束不同的同一类中创建相同的方法)。 The resolution algorithm first selects the best candidate, and only then checks if it verifies the constraints. 解析算法首先选择最佳候选者,然后才检查它是否验证约束。

In your case, if you ignore the where TBaseClassB : BaseClassB, new() constraint, the generic overload is a better candidate, because if TBaseClassB is DerivedClassA1 , it is a closer match than the non generic one ( Method(DerivedClassA1) is closer than Method(BaseClassA) ). 在您的情况下,如果忽略where TBaseClassB : BaseClassB, new()约束,则通用重载是更好的选择,因为如果TBaseClassBDerivedClassA1 ,则它比非通用Method(DerivedClassA1)更接近( Method(DerivedClassA1)Method(BaseClassA) )。 But then, it checks the constraint and sees that DerivedClassA1 doesn't inherit BaseClassB , which causes the error. 但是随后,它检查了约束,并发现DerivedClassA1不继承BaseClassB ,这会导致错误。

In other words, the non-generic overload has already been eliminated before the generic constraint is checked. 换句话说,在检查泛型约束之前,已经消除了非泛型过载。

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

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