当我们对应用程序进行开发时,整个程序是离不开变量的,变量本身是用来存储特定类型的数据。下面我们来学习变量的类型和一些基本的操作。
什么是变量变量是用来存储特定类型的数据,可以根据项目需要,随时改变变量中所存储的数据的值。
变量三要素包括:名称、类型和值。
变量名称:是变量在程序代码中的标识。
变量类型:确定变量所占用的内存大小和所代表的类型。
变量值:是指变量所代表的内存块中的数据。
在程序的执行过程中,变量的值可以发生变化,使用变量之前必须先对它进行声明,即声明变量,目的是指定变量的类型和变量的名称。
变量类型详解C#中的变量类型可以分为两种:
1、值类型:值类型的变量可以直接对数据进行存储。
2、引用类型:与值类型的数据存储方式不尽相同,它是存储实际数据的引用程序,通过此引用找到真正的数据。
值类型的特点:
值类型变量直接存储数据值,主要包含整数类型、浮点类型和布尔类型等。值类型变量在堆栈中进行分配,所以读取效率更高。使用值类型的主要目的是为了提高性能,其特点如下:
1、值类型变量存储在堆栈中。
2、访问值类型变量时一般都是直接访问实例。
3、对每一个值类型变量的操作,都不会影响其他变量。
4、使用值类型变量时,使用的是变量的值,而不是变量的内存地址值。
5、值类型变量不能为空值null,必须具有一个确定的值。
值类型是从System.ValueType类继承而来的类型,值类型中包含以下几种数据类型:
整数类型
整数类型代表一种没有小数点的整数数值,在C#中内置的整数类型有:
sbyte:8位有符号整数,值范围在-128-127
short:16位有符号整数,值范围在-32768-32767
int:32位有符号整数,值范围在-2147483648-2147483647
long:64位有符号整数,值范围在-9223372036854775808-9223372036854775807
byte:8位无符号整数,值范围在0-255

ushort:16位无符号整数,值范围在0-65535
uint:32位无符号整数,值范围在0-4294967295
ulong:64位无符号整数,值范围在0-18446744073709551615
byte类型以及short类型是范围比较小的整数,如果正整数的范围没有超过65535,可以声明为ushort类型,如果数值较小,可以使用byte类型,如果使用较小的数值类型时,此时要特别注意数值的大小,防止出现数值运算溢出的错误。
创建一个控制台应用程序,在其中声明一个int类型的变量intData,并对其进行初始化赋值为1025,再声明一个byte类型的变量byteData,并对其进行初始化赋值为254,然后将结果进行按行输出。代码如下:
staticvoidMain(string[]args){intintData=1025;//把1025赋值给变量intDatabytebyteData=254;把254赋值给变量byteDataConsole.WriteLine("变量intData={0}",intData);//输出intData值Console.WriteLine("变量byteData={0}",byteData);//输出byteData值Console.ReadLine();//按行读取}
Ctrl+F5运行,程序运行结果:
此时,如果将byteData变量赋值为257,重新编译程序,就会出现错误提示。其原因是byte类型的变量是8位无符号整数,它的范围在0-255之间,257已经超出了byte类型的范围,所以编译程序时会出现错误提示:
值得注意的是,在定义局部变量时要对其进行初始化,否则会出现错误提示:
浮点类型
浮点类型变量主要用于处理含有小数的数值,数据浮点类型主要包含float和double两种数值类型:
float类型:精确到7位数,范围1.5*10^(-45)~3.4*10^(38)。
double类型:儿精确到15~16位数,范围50*10^(-324)~1.7*10^(308)。
如果不做任何设置,包含小数点的数值都被默认为是double类型,如果要将数值以float类型来处理,就应该通过强制使用f或F将其指定为float类型。
下面的代码就是将数值强制指定为float类型:
floatintData=1025.00f;floatbyteData=254.00F;
如果要将数值强制指定为double类型,则需要使用d或D进行设置。下面的代码就是将数值强制指定为double类型:
DoubleintData=1025d;DoublebyteData=254D;
值得注意的是,如果需要使用float类型变量时,必须在数值的后面跟随f或者F。否则编译器会直接将其作为double类型处理,也可以在double类型的值前面加上float,对其进行强制转换。
布尔类型
布尔类型主要用来表示true或者false值,一个布尔类型的变量,其值只能是true或者false,不能将其他的值指定给布尔类型变量,布尔类型变量不能与其他类型进行转换。
如果将1025赋值给布尔类型变量boolX。代码如下:
boolboolX=1025;
这样赋值显然是错误的,编译器会返回错误提示,int值无法转换bool:
布尔类型变量大多数被应用到流程控制语句当中,如循环语句、条件语句等。
与定义局部变量不同,在定义全局变量时,如果没有特定的要求,不用对其进行初始化,整数类型和浮点类型的默认初始化为零,布尔类型的初始化为false。
引用类型:
引用类型是构建C#应用程序的对象类型数据,在应用程序执行的过程中,预先定义的对象类型,以new关键字来创建对象实例,并且存储在堆栈中。那什么是堆栈呢?
堆栈是一种由系统配置的内存空间,这个内存空间并没有特定大小,也没有时间长短,因此可以被随时随地运用于对象的访问。引用类型有以下几个特征:
1、必须在托管堆中为引用类型变量分配内存。
2、必须使用new关键字来创建引用类型变量。
3、在托管堆中分配的每个对象都有与之相关联的附加成员,这些成员必须被初始化。
4、引用类型变量的管理遵循垃圾回收机制。
5、多个引用类型变量可以引用同一对象,此时,对一个变量的操作会影响另一个变量引用的这个对象。
6、如果没有对引用类型变量进行赋值,则初始值为null。
所有类都是引用类型,包括类、接口、数组和委托。
创建一个控制台应用程序,创建一个名称叫Class1的类,并且在这个类中建立一个字段Value,并对其进行初始化,然后在程序的其他位置,通过new创建对该类的引用类型变量。
代码如下:
classProgram{staticvoidMain(string[]args){inta1=0;//声明int类型的变量a1,并初始化为0inta2=a1;//声明int类型的变量a2,并把a1的值赋给a2a2=1025;//对变量a2进行重新赋值Class1b1=newClass1();//使用new关键字创建引用类型变量b1Class1b2=b1;//使用new关键字创建引用类型变量b2,并将变量b1的值赋给b2b2.value1=124;//为引用类型变量b2中的value1值进行赋值Console.WriteLine("value1={0},{1}",a1,a2);Console.WriteLine("Refs:{0},{1}",b1.value1,b2.value1);Console.ReadLine();}classClass1{publicintvalue1=0;publicintvalue2=2;}}
程序运行的结果:
从结果能够看出,对于值类型变量a1和a2都保持各自的值,互不影响。而对于引用类型变量b1中的value1值被引用类型变量b2影响了,b1中的value1值最开始是0,当改变b2中的value1的值时,b1中的value1值也随之发生变化。
值类型与引用类型从概念上看,值类型直接存储值,而引用类型存储的是对值的引用,这两种类型存储在内存的不同地方,从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。
栈在编译时就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况,动态的分配内存的大小。因此,值类型总是在内存中占用一个预定义的空间大小(字节数),而引用类型的变量则为其分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,是存放实际值的地方。
打个比方,对于只收现金的个人小贩来说,你要买他的商品,值类型就相当于现金,要用就直接交付,而引用类型相当于银行卡,小贩没有POS机,要用得先去银行取出来,然后支付。
值类型在栈上分配内存
值类型如果作为方法中的局部变量,则被创建在线程栈上,如果该实例作为类型的成员,则作为类型成员的一部分,连同其他类型字段存放在托管堆上,每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值:
intx1=newint();等价于intx1=0;
当使用new运算符时,将调用特定类型的默认构造函数,并对变量赋予默认值。在上例中,默认构造函数将值0赋给了x1。
引用类型则在托管堆上分配内存
引用类型的实例创建在托管堆上,下面一段代码就足以说明值类型与引用类型的区别:
namespacemyConsole{classProgram{staticvoidMain(string[]args){Information.studentInformation();Console.ReadLine();}}publicclassStudent{publicstringname;publicintage;}publicstaticclassInformation{publicstaticvoidstudentInformation(){Studentperson1=newStudent{name="李明",age=18};Studentperson2=newStudent{name="张雨",age=21};intage1=person1.age;person1.age=19;//改变person1.age值Studentperson3=person2;person2.name="王雷";//改变person2.name值Console.WriteLine("person1:{0}的年龄:{1}",person1.name,person1.age);Console.WriteLine("age1的值:{0}",age1);Console.WriteLine("person2:{0}的年龄:{1}",person2.name,person2.age);Console.WriteLine("person3:{0}的年龄:{1}",person3.name,person3.age);}}}
运行结果:
从结果可以看出,当改变person1.age值时,age1没有变化,仍然是18,而当改变person2.name值时,person2.name值也跟着变了,这就是值类型和引用类型的区别。
前面说过,引用类型包含的只是堆上数据区域地址的引用,其实就是把person2的引用也赋给person3,它们指向了同一块内存区域,于是不管修改哪一个,另一个的值都会跟着改变,就像存折和银行卡一样,用银行卡取了钱,与之关联的存折上的钱也会跟着减少。
总结:理清了不同变量类型的特点和意义,对于我们编写程序大有裨益,在变量取值及赋值时就不容易发生错误。
结语:喜欢的请关注、转发!