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

标签 c# generics .net-4.0 overloading

采用以下代码:

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

标记为// 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'.

看起来方法重载正在选择 Operations.Method<TBaseClassB>(TBaseClassB) 方法重载而不是 Operations.Method(BaseClassA)给予时 DerivedClassA1 类型的参数,这与我的预期相反。 为什么是这样?难道我做错了什么?是否有替代/正确的实现方式 我想要的是调用 Method(BaseClassA)方法重载。

请注意,示例代码是我正在使用的一些真实代码的简化等价物 在。如果这个例子看起来做作,我们深表歉意。

最佳答案

重载决议不考虑泛型约束,因为这些约束实际上并不是方法签名的一部分(您不能在只有泛型约束不同的同一类中创建相同的方法)。解析算法首先选择最佳候选者,然后才检查它是否验证了约束。

在您的情况下,如果您忽略 where TBaseClassB : BaseClassB, new() 约束,则通用重载是更好的选择,因为如果 TBaseClassB DerivedClassA1,它比非泛型更接近匹配(Method(DerivedClassA1)Method(BaseClassA) 更接近)。但是随后,它检查约束并发现 DerivedClassA1 没有继承 BaseClassB,这导致了错误。

换句话说,在检查泛型约束之前,已经消除了非泛型重载。

关于c# - 当我期望它选择非泛型方法时,方法重载选择了泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21603034/

相关文章:

java - 通用方法不适用于参数

c# - "where"c sharp 类声明中的关键字

c# - 使用 NodaTime 将特定国家日期时间转换为 UTC

c# - Sprite 变化时自动调整 boxcollider2D

java - 更改泛型的空数组时出现意外的空指针异常

asp.net - 如何在 javascript 中禁用 Menu 控件的样式?

c# - 方法 'Boolean Contains..' 没有支持的 SQL 转换

c# - 为什么我不能使用 GcHandle.Alloc 固定枚举数组

c# - AWS DynamoDB 使用 QueryAsync 而不是 ScanAsync

c# - 如何将文件文档发送到打印机并进行打印?