十一:认识基元类型、FCL类型及与CLR的相容情况
基元类型(primitive),简单来说就是编译器直接支持的数据类型。基元类型直接映射到Framework类库(FCL)中的类型,例如C#中一个基元类型int直接映射到System.Int32类型,如下代码:
public sealed class Program
{
public static void Main()
{
int a = 0;
}
}
public sealed class Program
{
public static void Main()
{
System.Int32 a = 0;
}
}
第一种声明变量a时int是基元,颜色为蓝色,说明它是C#语言中的关键字,第二种System.Int32是Framework类库(FCL)在存在的类型,颜色为绿色,但它们编译生成的IL代码是完全相同的,如下所示:
//使用int声明变量a时的IL代码
.method public hidebysig static void Main() cil managed
{
.entrypoint
// 代码大小 4 (0x4)
.maxstack 1
.locals init ([0] int32 a)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ret
} // end of method Program::Main
//使用System.Int32声明变量a时的IL代码
.method public hidebysig static void Main() cil managed
{
.entrypoint
// 代码大小 4 (0x4)
.maxstack 1
.locals init ([0] int32 a)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ret
} // end of method Program::Main
为什么会有完全一样的IL代码呢,我们可以这样想像,C#编译器自动假定在所有源代码文件中添加了以下using指令:
using myInt32 = System.Int32;
//...等等一切基元类型
也就是加上了引用命名空间别名,所以就生成一完全一样的IL代码,但我们平时使用时使用哪一种用法呢,Jeffrey Richter推荐我们使用FCL类型,原因如下:
(1)很多开发人员在考虑不知道使用string还是String,object还是Object,bool还是Boolean,其实它们两者都没有区别,就是一个准确映射到别一个,都可以使用。
(2)在C#中,long映射到System.Int64,但在一种不同的编程语言中,long可能是映射到Int16或Int32。
(3)FCL的许多方法都将类型名称作为其方法名的一部分,例如,BinaryReader提供的包括ReaderBoolean,Reader32,ReaderSingle等,如下:
BinaryReader br = new BinaryReader();
float val = br.ReadSingle();//正确,但感觉不自然
Single val = br.ReadSingle();//正确,可读性强
下表为C#基元类型对应的FCL类型:
C#基元类型 |
FCL类型 |
CLS相容 |
Sbyte |
System.Sbyte |
否 |
byte |
System.Byte |
是 |
short |
System.Int16 |
是 |
ushort |
System.UInt16 |
否 |
int |
System.Int32 |
是 |
uint |
System.UInt32 |
否 |
Long |
System.Int64 |
是 |
ulong |
System.UInt64 |
否 |
char |
System.Char |
是 |
float |
System.Single |
是 |
double |
System.Double |
是 |
bool |
System.Boolean |
是 |
decimal |
System.Decimal |
是 |
object |
System.Object |
是 |
string |
System.String |
是 |