由于本章太多所以分成2-3文章(*~*)
基元类型
编译器直接支持的类型称为基元类型。基元类型直接映射到Framework类库中存在的类型,例如C#的int直接映射到System.Int32类型。
以下代码均为正确
int a = 0;//最方便
System.Int32 a = 0;//方便
int a = new int();//不方便
System.Int32 a = new System.Int32();//最不方便
只要是符合CLS规范的类型都有基元类型
可以认为C#自动假定所有源码文件都添加了
using sbyte = System.SByte;
using int = System.Int32;
using short = System.Int16;
C#语言规范规定最好使用关键字,而不是使用完整的系统名称。但是某些角度用这句话不是正确的。理由如下:
1.许多人纠结String还是string。由于C#的string直接映射到System.String(FCL类型),所以两者没有区别。类似一些开发者认为32位操作系的int是32位;64位操作系统int是64位。这是完全错误的。C#的int始终映射到System.Int32,所以无论什么操作系统始终是32位。如果程序员习惯使用Int32,就不会有这样的误解。
2.C#的long映射到System.Int64,但是在其他语言中可能是Int16或者Int32。比如C++/CLI就将long视为32,甚至大多数语言中long不是关键字。习惯一种编程语言容易产生误解
3.FCL许多方法名都把类型名2作为一部分。比如ToInt32,ReadInt32。
4.平时只用C#,的程序员逐渐忘记其他语言也可以写面向CLR的代码。
C#允许基元类型进行安全的隐式转化。如果不安全要求显示转换。安全指的是精度不会丢失。
C#Sing转int32是截断处理。
除了转型外基元类型还可以写成字面值。字面值可以看成类型本身的实例。比如下面123为实例调用实例方法
Console.WriteLine(123.ToString());
如果表达式由字面值构成。编译器在编译时可以完成表达式求治,增强程序性能。
Boolean found = false;
Int32 x = 20 + 50;
String a = "aa"+"ff";
check和unchecked
对于基元类型许多运算符可能导致溢出。溢出有时候是我们所不期待的,但是有极少时是我们希望的(计算哈希值或者校验和)。为此CLR提供了特殊IL指令允许编辑器选择恰当行为。CLR有一个add指令,作用是将两个值相加,但是不会检测溢出。还有一个add.ovf也是相加但是会检查溢出,在溢出时抛出System.OverflowException异常。除了加法,乘法,减法,数据转换都有类似的IL指令。sub.ovf,mul.ovf,conv.ovf。
c#默认情况下关闭溢出检查功能。让C#控制溢出的方法是/checked+编辑器开关。该开关会在使用代码时自动将加,减,乘,转换指令的无溢出版本。但是这样代价是代码执行时会稍微慢一点。
除了全局性打开,还可通过checked和unchecked操作符检查特定区域。这样更加灵活。
UInt32 a = unchecked((UInt32)(-1));//不会检测 a = 4294967295
Byte b = 100;
b = checked((byte)(200 + b));//会报错
}
C#还支持check/unchecck相关语句,他们语句块中所有表达式都进行/不进行检测。
unchecked
{
UInt32 a = unchecked((UInt32)(-1));//不会检测 a = 4294967295
}
checked
{
Byte b = 100;
b = (byte)(200 + b);//会报错
}
由于checked的作用仅仅是决定生成哪个版本的IL指令。在语句或操作符中使用方法不会造成任何影响。
checked
{
DoSomething();//该方法内checked管不到
}
建议
1.尽量使用有符号数值类型,不是无符号。类库的多个部分(Array和String的Length)被硬编码返回有符号的值。
2.合理使用checked和unchecked
3.建议开发是打开cheecked,生成应用时关闭,如果应用程序开始忍受check的性能损失,建议分布时也打开,可以防止安全漏洞或Bug。
Decimal类型在CLR中不是基元类型,意味着没有处理他的IL指令,checked,unccheck对他无效。如果不安全运算肯定会抛出OverflowExecption错误。
System.Numerics.BigInteger在内部使用UInt数组表示任意大的值,没有上下限所以演员不会有OverflowExecption异常