Microsoft.NET 框架程序设计 —— 基元类型、引用类型与值类型

        本文讨论.NET 框架开发人员经常遇到的各种数据类型。熟悉这些类型的不同行为对于一个开发人员来说至关重要。当我刚开始接触.NET框架时,就没有完全理解基元类型、引用类型和值类型之间的一些差别。这种模糊的认识甚至无意间导致了一些难以査找的bug以及性能问题。我希望通过本章的解释,能够帮助大家在提升代码效率的同时避免我曾遇到的一些麻烦。

5.1 基元类型

        某些数据类型的使用非常频繁,许多编译器都允许我们用某种简化的语法来操作它们。例如,我们可以用下面的语法来分配一个整数:

        System.Int32 a=new system.Int32();

        相信大家都会感到用这样的语法来声明和初始化一个整数未免太过麻烦。所幸,许多编译器(包括C#)都允许我们使用类似下面的语法来对整数进行声明和初始化:

        int a =0;

        这种语法大大提高了代码的可读性,并且经编译后和前一种语法生成的是同样的儿代码。编译器直接支持的数据类型称为基元类型(primitive type)。

        基元类型和.NET 框架类库(FCL)中的类型有直接的映射关系。例如,在#中,int直接映射为System.Int32 类型。因此,下面4行代码都能通过编译,并产生同样的I代码:

int a=0;                            //最便捷的语法
System.Int32 a=0;                   //较便捷的语法
int a= new int();                   //不便捷的语法
System.Int32 a=new System.Int32();  //不便捷的语法

        表5.1显示了FCL中的类型和它们在C#中对应的基元类型。对于那些和通用语言规范(CLS)兼容的类型,其他开发语言也都提供了类似的基元类型。但对于那些与CLS不兼容的类型,则无此必要。

表5.1 FCL类型及其在 C#中对应的基元类型

C#中的基元类型 FCL 类型 是否与 CLS 兼容 描 述
sbyte System.SByte 有符号8位值
byte System.Byte 无符号8位值
short System.Intl 6 有符号16位值
ushort System.UInt16 无符号16位值
int System.Int32 有符号32位值
uint System.UInt32 无符号32位值
long System.Int64 有符号64位值
ulong System.UInt64 无符号64位值
char System.Char 16 位 Unicode 字符(不像非托管 C++中那样,char表示的是一个8位值)
float System.Single IEEE32位浮点数
double System.Double IEEE 64位浮点数
bool System.Boolean 一个 True 或者 Flase值
decimal System.Decimal 128位高精度浮点值,通常用于不容许有舍入误差的金融计算场合。在这128位中,1位表示浮点值的符号,96位表示浮点值本身(译注:一个整数值,小数点位置由下面8个位来确定),8位表示用96位值除以浮点值所得结果的10的幂次(幂次范围为0~28)。其余的位尚未使用
object System.Qbiect 所有类型的基类型
string System.String 一个字符数组

         C#语言规范声称“作为一种编码风格,使用关键字应该优于使用完整的系统类型名称”。我个人不同意这段论述。我更喜欢使用FCL类型名,并且完全避免使用基元类型名称。实际上,我希望编译器甚至不要提供基元类型名称,并强制开发人员使用FCL类型名。理由如下:

  • 我发现很多开发人员都困惑于不知在代码中使用string还是 String。因为 C#中的 string(关键字)实际上映射了 System.String(FCL 类型),所以两者之间没有任何不同,都可以使用。
  • 在C#中,long 映射为 System.Int64,但是在其他的编程语言中,long 可能映射为一个 Int16或者 Int32。实际上,托管扩展 C++将 1ong看作是一个Int32。如果习惯了在一种语言下编程,再转而去阅读用另一种语言编写的代码就很容易误解其中的意图。实际上,大多数语言甚至不将 long 看作是关键字,也不会编译使用它的代码。
  • FCL,中有很多类型的方法都将一些类型名作为方法名称的一部分。例如,BinaryReader 类型就提供了诸如 ReadBoolean、ReadInt32、ReadSingle 之类的方法;而 System.Convert 类型也提供了诸如 ToBoolean、ToInt32、ToSingle 之类的方法。虽然下面的代码是合法的,但其中含有float的代码行在我看来总有些不自然,这段代码的正确性也并不明显:

BinaryReader br=new BinaryReader(...);

float val=br.ReadSingle();        //正确,但是有些不自然

Single val= br.Readsingle();    //正确,并且感觉也很自然

因为上面所有这些原因,本书将通篇采用FCL类型名。

在许多编程语言中,我们可能希望下面的代码能够正确地编译并执行:

Int32 i= 5;   //一个32位的值
Int64 l=i;    //隐式转型为一个64位的值

        大家可能会认为这段代码不能通过编译。毕竟,System.Int32和 System.Int64是不同的类型。但是,我们可能会很高兴看到C#编译器能够正确地编译这段代码,并且能够按我们的预期运行。为什么呢?

        这是因为 C#编译器熟悉基元类型,并且在编译代码时会应用自己的规则。换句话说,我们所选的编译器能够识别一些通用的编程模式,并产生必要的几,指令来使代码按期望的方式运行。

具体而言,编译器一般会支持和类型转换、文本常量(1iterals)、操作符相关的一些模式。看下面的例子。

        首先,编译器能够在基元类型之间进行隐式或者显式的转型:

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜飞鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值