泛型和从差异类调用重载方法 - 优先级问题[重复]
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<byte>.GetInt(20));
打印的是10
,而不是30
?
我一直认为 .NET 中的泛型是在运行时由 JIT 解析的。那么为什么jitter不够聪明,发现有ToInt32(byte)
方法,适合我们这里的byte
参数类型呢?
这种行为使Convert
静态类方法调用导致简单类型的装箱/拆箱操作。
【问题讨论】:
Test<byte>.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学习笔记之 优先考虑泛型和泛型方法