9

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

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

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<byte>.GetInt(20));打印10,而不是30

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

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

4

2 回答 2

7

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

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

于 2013-08-15T13:37:07.517 回答
0

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

我看透了IL 代码的Reflector并发现了这个 -

.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 在这里提到的,您可以调用 byte 方法,使用dynamic它在执行时而不是编译时提供类型化信息。

public static class Test<T>
{
    public static int GetInt(T source)
    {
        dynamic dynamicSource = source;
        return Convert.ToInt32(dynamicSource );
    }
}
于 2013-08-15T13:43:30.537 回答