大家好,欢迎来到IT知识分享网。
当我们对应用程序进行开发时,整个程序是离不开变量的,变量本身是用来存储特定类型的数据。下面我们来学习变量的类型和一些基本的操作。
什么是变量
变量是用来存储特定类型的数据,可以根据项目需要,随时改变变量中所存储的数据的值。
变量三要素包括:名称、类型和值。
变量名称:是变量在程序代码中的标识。
变量类型:确定变量所占用的内存大小和所代表的类型。
变量值:是指变量所代表的内存块中的数据。
在程序的执行过程中,变量的值可以发生变化,使用变量之前必须先对它进行声明,即声明变量,目的是指定变量的类型和变量的名称。
变量类型详解
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,然后将结果进行按行输出。代码如下:
static void Main(string[] args)
{
int intData = 1025;//把1025赋值给变量intData
byte byteData = 254;把254赋值给变量byteData
Console.WriteLine("变量intData={0}", intData);//输出intData值
Console.WriteLine("变量byteData={0}", byteData);//输出byteData值
Console.ReadLine();//按行读取
}
IT知识分享网
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类型:
IT知识分享网float intData = 1025.00f;
float byteData = 254.00F;
如果要将数值强制指定为double类型,则需要使用d或D进行设置。下面的代码就是将数值强制指定为double类型:
Double intData = 1025d;
Double byteData = 254D;
值得注意的是,如果需要使用float类型变量时,必须在数值的后面跟随f或者F。否则编译器会直接将其作为double类型处理,也可以在double类型的值前面加上float,对其进行强制转换。
布尔类型
布尔类型主要用来表示true或者false值,一个布尔类型的变量,其值只能是true或者false,不能将其他的值指定给布尔类型变量,布尔类型变量不能与其他类型进行转换。
如果将1025赋值给布尔类型变量boolX。代码如下:
IT知识分享网 bool boolX = 1025;
这样赋值显然是错误的,编译器会返回错误提示,int值无法转换bool:
布尔类型变量大多数被应用到流程控制语句当中,如循环语句、条件语句等。
与定义局部变量不同,在定义全局变量时,如果没有特定的要求,不用对其进行初始化,整数类型和浮点类型的默认初始化为零,布尔类型的初始化为false。
引用类型:
引用类型是构建C#应用程序的对象类型数据,在应用程序执行的过程中,预先定义的对象类型,以new关键字来创建对象实例,并且存储在堆栈中。那什么是堆栈呢?
堆栈是一种由系统配置的内存空间,这个内存空间并没有特定大小,也没有时间长短,因此可以被随时随地运用于对象的访问。引用类型有以下几个特征:
1、必须在托管堆中为引用类型变量分配内存。
2、必须使用new关键字来创建引用类型变量。
3、在托管堆中分配的每个对象都有与之相关联的附加成员,这些成员必须被初始化。
4、引用类型变量的管理遵循垃圾回收机制。
5、多个引用类型变量可以引用同一对象,此时,对一个变量的操作会影响另一个变量引用的这个对象。
6、如果没有对引用类型变量进行赋值,则初始值为null。
所有类都是引用类型,包括类、接口、数组和委托。
创建一个控制台应用程序,创建一个名称叫Class1的类,并且在这个类中建立一个字段Value,并对其进行初始化,然后在程序的其他位置,通过new创建对该类的引用类型变量。
代码如下:
class Program
{
static void Main(string[] args)
{
int a1 = 0;//声明int类型的变量a1,并初始化为0
int a2 = a1; //声明int类型的变量a2,并把a1的值赋给a2
a2 = 1025; //对变量a2进行重新赋值
Class1 b1 = new Class1();//使用new关键字创建引用类型变量b1
Class1 b2 = b1;//使用new关键字创建引用类型变量b2,并将变量b1的值赋给b2
b2.value1 = 124; //为引用类型变量b2中的value1值进行赋值
Console.WriteLine("value1={0},{1}", a1,a2);
Console.WriteLine("Refs:{0},{1}", b1.value1,b2.value1);
Console.ReadLine();
}
class Class1
{
public int value1 = 0;
public int value2 = 2;
}
}
程序运行的结果:
从结果能够看出,对于值类型变量a1和a2都保持各自的值,互不影响。而对于引用类型变量b1中的value1值被引用类型变量b2影响了,b1中的value1值最开始是0,当改变b2中的value1的值时,b1中的value1值也随之发生变化。
值类型与引用类型从概念上看,值类型直接存储值,而引用类型存储的是对值的引用,这两种类型存储在内存的不同地方,从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。
栈在编译时就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况,动态的分配内存的大小。因此,值类型总是在内存中占用一个预定义的空间大小(字节数),而引用类型的变量则为其分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,是存放实际值的地方。
打个比方,对于只收现金的个人小贩来说,你要买他的商品,值类型就相当于现金,要用就直接交付,而引用类型相当于银行卡,小贩没有POS机,要用得先去银行取出来,然后支付。
值类型在栈上分配内存
值类型如果作为方法中的局部变量,则被创建在线程栈上,如果该实例作为类型的成员,则作为类型成员的一部分,连同其他类型字段存放在托管堆上,每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值:
int x1 = new int();
等价于
int x1 = 0;
当使用new运算符时,将调用特定类型的默认构造函数,并对变量赋予默认值。在上例中,默认构造函数将值0赋给了x1。
引用类型则在托管堆上分配内存
引用类型的实例创建在托管堆上,下面一段代码就足以说明值类型与引用类型的区别:
namespace myConsole
{
class Program
{
static void Main(string[] args)
{
Information.studentInformation();
Console.ReadLine();
}
}
public class Student
{
public string name;
public int age;
}
public static class Information
{
public static void studentInformation()
{
Student person1 = new Student { name = "李明", age = 18 };
Student person2 = new Student { name = "张雨", age = 21 };
int age1 = person1.age;
person1.age = 19;//改变person1.age值
Student person3 = 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,它们指向了同一块内存区域,于是不管修改哪一个,另一个的值都会跟着改变,就像存折和银行卡一样,用银行卡取了钱,与之关联的存折上的钱也会跟着减少。
总结:理清了不同变量类型的特点和意义,对于我们编写程序大有裨益,在变量取值及赋值时就不容易发生错误。
结语:喜欢的请关注、转发!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/6784.html