泛型和从差异类调用重载方法 - 优先级问题[重复]

Posted

技术标签:

【中文标题】泛型和从差异类调用重载方法 - 优先级问题[重复]【英文标题】:Generics and calling overloaded method from difference class - precedence issue [duplicate] 【发布时间】:2013-08-17 16:57:51 【问题描述】:

首先,对不起标题,但我想不出更好的...

我的问题可以通过简单的代码示例来呈现:

public static class Test<T>

    public static int GetInt(T source)
    
        return Convert.ToInt32(source);
    


public static class Convert

    public static int ToInt32(byte source)
    
        return 30;
    

    public static int ToInt32(object source)
    
        return 10;
    

为什么Console.WriteLine(Test&lt;byte&gt;.GetInt(20)); 打印的是10,而不是30

我一直认为 .NET 中的泛型是在运行时由 JIT 解析的。那么为什么jitter不够聪明,发现有ToInt32(byte)方法,适合我们这里的byte参数类型呢?

这种行为使Convert 静态类方法调用导致简单类型的装箱/拆箱操作。

【问题讨论】:

Test&lt;byte&gt;.GetInt(byte.Parse("20")) 也返回 10,我觉得这很奇怪,监视窗口显示类型是 objectbyte,这可能会提供一些关于发生了什么的线索 【参考方案1】:

编译器必须在编译时决定选择哪种方法。它不会发出任何代码来决定在运行时选择两个重载中的哪一个。因为您没有向 C# 编译器提供任何证据表明 GetInt(T source) 仅适用于 byte 结构,所以编译器必须选择另一个重载。

或者让我换个角度说:如果你删除了ToInt32(object) 重载,你的程序就无法编译。

【讨论】:

有没有办法让它调用byte 方法(或者一般来说,最好的方法)? 检查 typeof(T) == typeof(byte) + 如果 true 是唯一方法,则强制转换为 byte @MarcinJuraszek:拳击真的有问题吗? @Steven 是的,因为它会带来不必要的性能损失。【参考方案2】:

编译器在编译时决定执行哪个方法。

我通过 Reflector 看到 IL 代码 并找到了这个 -

.method public hidebysig static int32 GetInt(!T source) cil managed

    .maxstack 1
    .locals init (
        [0] int32 CS$1$0000)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: box !T
    L_0007: call int32 ConsoleApplication1.Convert::ToInt32(object) <-- HERE
    L_000c: stloc.0 
    L_000d: br.s L_000f
    L_000f: ldloc.0 
    L_0010: ret 

正如 Jon Skeet here 所述,您可以使用 dynamic 调用字节方法,它在执行时而不是编译时提供类型化信息。

public static class Test<T>

    public static int GetInt(T source)
    
        dynamic dynamicSource = source;
        return Convert.ToInt32(dynamicSource );
    

【讨论】:

以上是关于泛型和从差异类调用重载方法 - 优先级问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Java:Effective java学习笔记之 优先考虑泛型和泛型方法

Java:Effective java学习笔记之 优先考虑泛型和泛型方法

typeof 泛型和强制类型 [重复]

打字稿、泛型和重载

c#泛型方法重载

泛型和枚举