我正在测试一个简单的程序来重载整数参数:
class Program
{
public static void Foo(Int16 value)
{
Console.WriteLine("Int16");
}
public static void Foo(Int32 value)
{
Console.WriteLine("Int32");
}
public static void Foo(Int64 value)
{
Console.WriteLine("Int64");
}
static void Main(string[] args)
{
Foo(10);
}
}
现在我知道这些类型的容量是这样的:
Type Capacity
Int16 -- (-32,768 to +32,767)
Int32 -- (-2,147,483,648 to +2,147,483,647)
Int64 -- (-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807)
现在Foo(10)
调用Int32
重载。为什么? 10的值不能适合Int16
吗?
让我感到困惑的是,当我删除Int32
重载时,会调用Int16
重载。那是为什么?
答案 0 :(得分:4)
如果在没有后缀的代码中指定整数文字,根据C#规范第2.4.4.2节“整数文字”,它会得到类型int
,uint
或{{1} },取决于哪种类型可以保持其值。
所以你的long
是10
,所以没有任何改变。
现在有趣的是,如果删除Int32
重载,Int32
仍然是10
,但是可以调用可以容纳该值的最小类型的重载,在这种情况下Int32
。
我无法快速找到指定的位置,但您可以在生成的IL中看到它:
Int16
编译器可以这样做,因为.method public hidebysig static void Main(string[] args) cil managed
{
//
.maxstack 8
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: call void Program::Foo(int16)
IL_0008: nop
IL_0009: ret
} // end of method Program::Main
是一个常量,因此信息在编译时是已知的(而不是它是一个变量)。正如Eric Lippert states it:
它可以隐式转换为所有内置数字类型。因此,当要求选择最佳过载时,重载决策将首先选择完全匹配 -
10
- 如果可用。如果没有,那么它将选择唯一最具体的类型(如果有的话)。int
比short
更具体,因为所有空头都可以转换为多头,但并非所有多头都可以转换为空头。
另见:
答案 1 :(得分:2)
解释了默认映射here
正如Hans Passant所说,解除Int32
重载时发生的事情已解释为here
Foo.Bar(10)
表示10是const int
而不是int
。现在有道理。const int
达到编译器可以将int固定为最小的大小,即[{short
=Int16
],如果是10.int
将获得自己的大小或更大,即long
[=Int64
] - basarat
_
推理是:一个常量整数可以隐式转换为它适合的任何整数类型,因此所有三种方法都适用。我们现在必须确定三种适用方法中哪一种最好。它是具有最具体参数类型的那个。类型X比类型Y更具体,如果“所有X都可以转换为Y而不是所有Y都可以转换为X”。也就是说,长颈鹿比动物更具特异性,因为所有长颈鹿都是动物,但反之亦然。 [
short
=Int16
]比long
[=Int64
]更具体,因此获胜。 - Eric Lippert
Eric可能知道这一点,he was on the Microsoft C# language development team ......