.NET C# Web开发学习之路——数据类型、类型转换、变量、常量
本文根据以下内容来说明:
- 数据类型
- 数据类型转换
- 声明并使用变量
- 声明并使用常量
1. 数据类型
C#认可的基础数据类型并没有内置于C#语言中,二是内置于.NET Framework中。C#有15个预定义类型,其中13个是值类型,2个是引用类型(object和string)。
1.1 值类型
值类型直接存储数据值,主要包含整数类型、浮点类型以及布尔类型等。值类型在堆栈中进行分配,因此效率很高,使用值类型的目的也是为了提高性能。
1.1.1 整型
类型 | 说明 | 范围 |
---|---|---|
sbyte | 8位有符号整数 | -128~127 |
short | 16位有符号整数 | -32768-32767 |
int | 32位有符号整数 | -2147473648-2147483647 |
long | 64位有符号整数 | -9223372036854775808~9223372036854775807 |
byte | 8位无符号整数 | 0~255 |
ushort | 16位无符号整数 | 0~65535 |
uint | 32位无符号整数 | 0-4294967295 |
ulong | 64位无符号整数 | 0~18446744073709551615 |
1.1.2 浮点类型
类型 | 说明 | 范围 |
---|---|---|
float | 精确到7位数 | 1.5*10e-45 ~ 3.4 *10e38 |
double | 精确到15~16位数 | 50 * 10e-324~1.7 * 10e308 |
float数据类型用于较小的浮点数,因为要求精度较低。double数据类型比float数据类型大,提供的精度也大一倍(15位)。如果在代码中没有对某个非整数值(如123)硬编码,则编译器一般假定该变量是double。
如果想制定该值为float,可以在字符后面加上字符F(或者f)。例如:
float a = 4.5F;
1.1.3 decimal类型
类型 | 说明 | 范围 |
---|---|---|
decimal | 128位高精度十进制表示法 | 正负1.0*10e-28~正负7.9*10e2 |
decimal类型专门用于进行财务计算,使用decimal类型提供的28位的方式取决于用户。要把数字指定为decimal类型,可以在数字的后面加上字符M(或者m).例如:
decimal d = 14.50M;
1.1.4 布尔(boolean)类型
类型 | 说明 | 值 |
---|---|---|
bool | 表示true或者false | true或者false |
1.1.5 char字符类型
类型 | 说明 |
---|---|
char | 表示一个16位的(Unicode)字符 |
char类型的字变量是用单引号引起来的。如:
'A'
如果把字符A放在双引号内,编译器会把它当做字符串,从而产生错误。
1.1.6 值类型特征
- 值类型变量都存储在堆栈中
- 访问值类型变量时,一般都是直接访问其实例
- 没个值类型变量都有自己的数据副本,因此对一个值类型变量的操作不会影响其他变量
- 复制值类型变量时,复制的是变量的值,而不是变量的地址
- 值类型变量不能为null,必须有一个确定的值。
1.2 引用类型
1.2.1 引用类型
类型 | 说明 |
---|---|
object | object类型在.NET Framework中是Object的别名。在C#的同一类型中,所有类型(预定义类型、用户自定义类选哪个、引用类型和值类型)都是直接或间接从Object继承而来的 |
string | string类型表示零或更多Unicode字符组成的序列(字符串) |
注意:尽管string是引用类型,但如果用到了相等运算符(== 和!=),则表示比较string对象而不是引用的值。
1.2.2 引用类型特征
- 必须在托管堆中卫引用类型变量分配内存
- 必须是用new关键字来创建引用类型变量
- 在托管堆中分配的没个对象都有与之关联的附加成员,这些成员必须被初始化
- 引用类型变量是由垃圾回收机制(GC)来管理的
- 多个引用类型变量可以引用同意对象,此时对一个变量的操作会影响另一个变量所引用的同一对象。
- 引用类型被赋值前的值都是
2. 声明并使用变量
2.1 变量的声明和初始化
变量的声明是指定变量的名称和类型。未经声明的变量本身不合法,也无法在程序中是用。C#中,声明一个变量是由一个类型和跟在后面的一个或多个变量名组成。多个变量之间逗号隔开,分号结束。例如:
int intOne; //声明了一个名称为intOne的整型变量
string str1,str2,str3; //声明了三个字符型变量,分辨是str1,str2,str3
声明变量时还可以初始化,即在每个变量名后面加上给变量赋初始值的指令。例如:
int a = 2018; //声明了一个int型的变量,并初始化为 2018;
string x = "Hello World!",y = "Call me",z = "你来自哪里?"; //声明了三个字符串变量x,y,z,并分别初始化为“Hello World!”,“Call me”,“你来自哪里?”
2.2 变量的命名规则
- 变量只能由数字、字母、下划线组成。(不建议使用中文)
- 变量名的第一个符号只能是字母或者下划线,不能是数字。
- 不能是用关键字作为变量名
- 变量名是区分大小写的
- 一旦在一个语句块里定义了一个变量名,那么在变量的作用域内不能再定义同名的变量
2.3 变量的作用域
变量的作用域就是可以访问该变量的代码区域。一般情况下,可以通过以下规则来确定变量的作用域:
- 只要字符所属的类在某个作用域内,其字段也在改作用域内。
- 局部变量存在于声明该变量的语句块或方法结束的封闭花括号之前的作用域。
- 在for、while或类似语句中声明的局部变量存在于改循环体
- 全局变量的作用域是该变量所存在的命名空间
3.声明并使用常量
常量就是器值固定不变的数据,常量的值在编译时就已经确定。常量的类型只能为sbyte、byte、short、unshort、int、unint、long、unlong、char、float、double、decimal、bool、string。C#中使用关键字const来声明常量,并且在声明常量的时候必须初始化。
例:
class Program
{
static void Main(string[] args)
{
int a = 213;
const int b = 666;
Console.WriteLine("变量a={0}",a);
Console.WriteLine("常量b={0}",b);
a = 999;
Console.WriteLine("变量a={0}", a);
}
}
如果尝试去修改常量b的值,编译器会报错,阻止这样的操作。
4. 数据类型转换
4.1 隐式类型转换
隐式类型转换就是不需要声明就能进行的转换。进行隐式类型转换时,编译器不需要检查就能安全的进行转换。下表列出了可以进行隐式类型转换的数据类型:
源类型 | 目标类型 |
---|---|
sbyte | short、int、long、float、double、decimal |
byte | short、ushort、int、uint、long、ulong、float、double或decimal |
short | int、long、float、double或decimal |
ushort | int、uint、long、ulong、float、double或decimal |
int | long、float、double或decimal |
unint | long、ulong、float、double或decimal |
long | float、double或decimal |
ulong | float、double或decimal |
char | ushort、int、uint、long、ulong、float、double或decimal |
float | double |
说明:从int、uint、long到float,以及从long或ulong到double的转换可能导致精度损失,但不会影响其数量级;其他隐式类型转换则不会丢失任何信息。
例:将int类型的值隐式转换成long类型
int i = 927; //声明一个int型变量并初始化为927
long j = i; //隐式转换成long类型
4.2 显式类型转换
显式类型转换也可以成为强制类型转换,它需要在代码中明确地声明要转换的类型。如果在不存在隐式类型转换的类型之间进行转换,就需要使用显式类型转换。下表列出了需要进行显式类型转换的数据类型:
源类型 | 目标类型 |
---|---|
sbyte | byte、ushort、uint、ulong 或 char |
byte | sbyte、char |
short | sbyte、byte、ushort、uint、ulong 或 char |
ushort | sbyte、byte、short 或 char |
int | sbyte、byte、short、ushort、uint、ulong 或 char |
uint | sbyte、byte、short、unshort、int 或 char |
char | sbyte、byte 或 short |
float | sbyte、byte、short、ushort、int、uint、ulong、long、char 或 decimal |
ulong | sbyte、byte、short、ushort、int、uint、long 或 char |
long | sbyte、byte、short、ushort、int、uint、ulong 或 char |
double | sbyte、byte、short、ushort、int、uint、ulong、long、char或decimal |
decimal | sbyte、byte、short、ushort、int、uint、ulong、long、char或double |
例子:将double类型的强制转换成int类型
double x = 19810927.0112; //声明一个double类型的变量并初始化为19810927.0112
int y = (int)x; //将double类型的x 强制转换成int类型的y;等同于 int y = Convert.ToInt32(x);
4.3 装箱
实质上是将值类型装换为引用类型的过程。下面的代码用来对int类型的变量 i 进行装箱操作:
int i = 2018; //声明一个值类型变量
object obj = i; //对值类型变量进行装箱操作
例子:创建一个控制台应用程序,声明一个整型变量 i 并初始化值,然后将其赋值到装箱对象obj中,然后在改变变量i的值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _11zhuangxiang
{
class Program
{
static void Main(string[] args)
{
int i = 2018;
object obj = i;
Console.WriteLine("1、i 的值为{0},装箱后的对象为{1}",i,obj);
i = 2019;
Console.WriteLine("2、i 的值为{0},装箱后的对象为{1}",i,obj);
Console.ReadLine();
}
}
}
程序运行结果为:
1、i 的值为2018,装箱后的对象为2018
2、i 的值为2019,装箱后的对象为2018
从程序运行结果可以看出,值类型变量的值复制到装箱得到的对象中,装箱后改变值类型的值,并不会影响装箱对象的值。
4.4 拆箱
实质上是将引用类型转换为值类型的过程。拆箱大致可以分下面两个阶段:
- 检查对象的实例,看它是不是值类型的装箱值
- 把这个实例的值复制给值类型的变量
例:创建一个控制台应用程序,声明一个整型变量 i 并初始化,然后将其复制到装箱对象obj中,最后进行拆箱操作,将装箱对象obj赋值给整型变量 j 。代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _12chaixiang
{
class Program
{
static void Main(string[] args)
{
int i = 2018;
object obj = i;
Console.WriteLine("装箱操作:值为{0},装箱后对象为{1}", i, obj);
int j = (int)obj;
Console.WriteLine("拆箱操作:装箱对象为{0},值为{1}",obj,j);
Console.ReadLine();
}
}
}
程序运行结果为:
装箱操作:值为2018,装箱后对象为2018
拆箱操作:装箱对象为2018,值为2018
从程序运行结果可以看出,拆箱后得到的值类型数据的值与装箱对象相等。