C#8.0本质论第二章--数据类型

C#8.0本质论第二章–数据类型

2.1基本数据类型

C#的基本数据类型都有关键字与之关联,decimal是特殊的浮点数类型,能存储大数字而无表示错误。

2.1.1整数类型

C#中有8种整数类型

类型大小BCL名称后缀
sbyte8位System.SByte
byte8位System.Byte
short16位System.Int16
ushort16位System.UInt16
int32位System.Int32
uint32位System.UInt32U或u
long64位System.Int64L或l
ulong64位System.UInt64UL或ul

C#所有基元类型都有短名称和完整名称,完整名称对应**BCL(基类库)**中的类型名称,该名称在所有语言中都相同,对程序集中的类型进行了唯一性标识。从编译器角度看,最终生成的CIL代码看不出源代码具体使用的是哪一种。不要时而用短名称时而用完整名称,比如用string而不是System.String。

2.1.2浮点类型

浮点数精度可变,除非分母恰好是2的整数幂,否则用二进制浮点类型无法准确表示该数比如0.1容易表示成0.09999999…或者0.10000…1,

类型大小BCL名称有效位数后缀
float32位System.Single7F或f
double64位System.Double15-16D或d
2.1.3decimal类型
类型大小BCL名称有效位数后缀
decimal128位System.Decimal28-29M或m

和浮点数不同,decimal类型保证范围内的所有十进制数都是精确的,但是它的范围较小,计算速度稍慢,但差别不大可以忽略不计。之所以用m表示decimal是因为这种数据类型经常用于货币(monetary)计算。

2.1.4字面值

字面值(literal value)表示源代码中的固定值。直接将值放到源代码中称为硬编码(hardcoding)。默认情况下输入带小数点的字面值,编译器会自动把它解释成double类型,整数值通常默认为32位int,如果值太大编译器会把它解释成long。此外,C#编译器允许向非int的数值类赋值,如:

short s = 42;
byte b = 77;

这一点仅对字面值成立,而下面是非法的:

b = s;

有时数字很大,为了解决可读性问题,C#7.0新增了对数字分隔符的支持,可在书写字面值时用下划线(_)分割,如9_814_072_356

0x002A表示16进制42,从C#7.0开始可将数字表示成二进制值,如0b101010表示42,从C#7.2开始可以把数字分隔符放到x或b后面

输出时可以将数字格式化成十六进制:

//输出0x2A,即十六进制的42
System.Console.Writeline($"0x{42:X}");

为了更准确地表示double值的字符串形式,可以使用格式字符串和**round-trip格式说明符R(或r)**进行转换。

2.2更多基本类型

2.2.1布尔类型
类型大小BCL名称
bool8位System.Boolean

虽然一个二进制位足以容纳布尔一个类型的值,但是在C#里bool实际是一个字节大小

2.2.2字符类型
类型大小BCL名称
char16位System.Char

char表示16位字符,虽然大小和ushort相同,但是char是C#特有类型,要单独对待(C++里是8位)。

反斜杠和特殊字符代码统称为转义序列(escape sequence)

2.2.3字符串
类型BCL名称
stringSystem.String

零或多个字符的有限序列称为字符串

C#允许在字符串前使用@符号,指明转义序列不被处理,结果是一个逐字字符串字面值(verbatim string literal)。(对应C++11里的raw string)。

和C++不同的是,C#不自动连接字符串字面值。(是的,C++里"ab" “cd"会自动连接成"abcd”)。

假如同一字符串面值在程序集中多次出现,那么编译器在程序集中只定义字符串一次,且所有变量都指向它。

逐字和插值可组合使用,先指定$再指定@。

字符串插值是调用string.Format()方法的语法糖,比如:

//表面上
System.Console.Writeline($"your name is {firstname},{lastname}.");
//实际上
object[] args = new object[] {firstname,lastname};
System.Writeline($"your name is {0},{1}.",args);

实现了某种程度上的本地化支持,不会因为字符串造成编译后代码注入。

一些字符串方法:Format,Concat,Compare,StartsWith,EndsWith,ToLower,ToUpper,Trim,TrimEnd,Replace.

之前调用静态方法需附加如命名空间和类型名前缀,可利用C#6.0新增的using static指令避免这些前缀。只支持静态方法和属性。

如果要在插值或格式化的字符串中添加实际的左右大括号,可连写两个大括号来表示,如$“{{ {123} }}“表示字符串”{ 123 }”.

输出换行所需的字符由操作系统决定,Windows的换行符是\r和\n两个字符组合,而UNIX是单个\n,

要依赖System.WriteLine()和System.Enviroment.NewLine()而不是\n来确保跨平台兼容。

C#语法允许像访问成员变(在C#中称为字段)量那样访问属性(Property),属性定义了称为**赋值方法(setter)取值方法(getter)**的特殊方法

string类型的关键特征是它不可变(immutable),处于性能考虑,没有提供修改现有字符串内容的机制,不可能在同一个内存位置将字符串中的字母全部转换成大写,只能在其他位置新建字符串,让它成为旧字符串大写字母版本,而旧字符串不会被修改。

如有大量字符串需要修改,可考虑使用System.Text.StringBuilder类型而不是string。

2.2.4null和void

将null赋给引用类型的变量和根本不赋值是不一样的概念。将null赋给string变量和为变量赋值""也不是一样的概念。

声明变量时在名称后加一个问号,表示该变量可以被设置为null,这便是可空修饰符(C#2.0后)。

在C#8.0之前,可控修饰符不能用于引用类型变量的声明,从C#8.0开始,有了可空引用类型的概念,若要启动,则需要在声明变量之前任意位置放置"#nullable enable"语句。被启用时将没有可控修饰符的变量设置为null将会产生警告信息。

void有两个含义:标记方法不返回任何值,以及代表指向未知类型的存储位置的一个指针,但这种在C#中比较罕见。

2.3数据类型转换

有可能造成数据丢失或抛出异常的任何转换都要执行显示转型。相反的都可以进行隐式转型。

2.3.1显示转型

默认情况下,容不下的数据在赋值时会悄悄地溢出,但将代码放到checked块中,就会使运行时引发System.OverflowException异常:

checked
{
	int n = inr.MaxValue+1;
}

还支持unchecked块强制不进行溢出检查。

C#不支持从数值类型到布尔类型的有效转换,是为了避免可能发生的歧义,还有助于避免用户在本应使用相等操作符的时候用赋值操作符。

2.3.2隐式转型
2.3.3不使用转型操作符的类型转换

每个数值数据类型都包含一个Parse()方法,允许将字符串转换成对应的数值类型,还可以用特殊类型System.Convert()。

所有类型都支持ToString()方法。

从C#2.0起,所有基元数值类型都包含静态TryParse()方法,与Parse()的区别是,转换失败不是抛出异常,而是返回false。

从C#7.0开始不用先声明只准备作为out参数使用的变量,该变量在if内部和外部均可使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值