3.变量与常量

1 变量的基本概念

变量本身被用来存储特定类型的数据,可以根据需要随时改动变量中所储存的数据值。变量具有名称、类型、值。变量名是变量在程序源代码中的标识。变量类型确定它所代表的的内存大小和类型,变量值是指它所代表的内存块中的数据。在程序的执行过程中,变量的值可以发生变化。使用变量之前必须声明变量,即指定变量的类型和名称。

2 变量的声明及赋值

变量的使用是程序设计中一个十分重要的环节。为什么要定义变量呢?就是要告诉编译器(Compiler)这个变量是属于哪一种数据类型,这样编译器才知道需要配置多少空间给它,以及它能存放什么样的数据。在程序运行的过程中,空间内的值是变化的,这个内存空间就称为变量。声明变量就是指定变量的名称和类型。声明变量可以一个类型后面跟多个变量,也可以在声明变量的同时给变量赋值。

string str1,str2;
int a=1,b=2,c=3;

3 变量的作用域

由于变量被定义出来后只是暂存在内存中,等到程序执行到某一个点后,该变量会被释放掉,也就是说变量有他的声明周期。变量的作用域是指程序代码能够访问该变量的区域,若超出该区域,则在编译时
会出现错误。

3.1 成员变量

在类体中定义的变量称为成员变量,成员变量在整个类中都有效。类的成员变量又可分为静态变量实例变量俩种。

class Test
{
    
    
	int x = 45;	   //实例变量
	static int y = 90;  //静态变量,也称类变量
}

如果在成员变量的前面加上关键字static,这样的成员变量称为静态变量。静态变量的有效范围可以跨类,甚至可以达到整个应用程序之内。对于静态变量,除了能在定义它的类内存取,还能直接以“类名.静态变量”的方式在其他类内使用。

3.2 局部变量

局部变量只在当前的代码块中有效。在类的方法中声明变量,包括方法的参数都属于局部变量。局部变量只有在当前方法中有效,不能用于类的其他方法。局部变量的生命周期取决于方法,当方法被调用时,C#编译器为方法中的局部变量分配内存空间,当该方法的调用结束后,则会释放方法中局部变量占用的内存空间,局部变量也会被销毁。

4 数据类型

C#中的变量类型根据其定义可以分为俩种:值类型和引用类型。这俩种类型的差异在于数据的储存方式,值类型的变量本身直接存储数据,而引用类型则存储实际数据的引用。

4.1 值类型

值类型变量直接存储其数据值,主要包含整数类型、浮点类型、布尔类型等。值类型变量在栈中进行分配,因此效率很高,使用值类型主要是为了提高性能。值类型具有如下特点:

  1. 值类型变量都存储在栈中。
  2. 访问值类型变量时,一般都是直接访问其实例。
  3. 每个值类型数据都有自己的数据副本,因此对一个值类型变量的操作不会影响其他变量。
  4. 复制值类型变量时,复制的是变量的值,而不是变量的地址。
  5. 值类型变量不能为null,必须具有一个确定的值。
    值类型是从System.ValueType继承而来的类型。

4.1.1 整数类型

整数类型用来存储整数数值,即没有小数部分的值。可以使整数,也可以是负数。整形数据在C#中有三种表示形式:十进制、八进制、十六进制
十进制:不能以 0 作为数的开头。
八进制:必须以 0 作为数的开头。
十八进制:必须以 0X0x 作为数的开头。

C#内置证书类型如下表:

类型 说明( 8 位等于 1 字节) 范围
sbyte 8位有符号整数 -28-1 ~ 28-1-1
short 16位有符号整数 -216-1 ~ 216-1-1
int 32位有符号整数 -232-1 ~ 2321-1
long 64位有符号整数 - 264-1 ~ 264-1-1
byte 8位无符号整数 0 ~ 28-1
ushort 16位无符号整数 0 ~ 216-1
unit 32位无符号整数 0 ~ 232-1
ulong 64位无符号整数 0 ~ 264-1

字节中存放的为二进制数字,所以范围是有计算公式的,就是通过二进制位数判断十进制的取值范围,有符号位数的第一个字节存放正负,其余存放二进制数字。

4.1.2 浮点类型

浮点类型变量主要用于处理含有小数的数值数据,浮点类型主要包含floatdouble俩种数值类型。

类型 说明
float 精确到7位数
double 精确到15~16位数

如果不做任何设置,包含小数点的数值都别认为是double类型,如果要将数值以float类型来处理,需要通过强制使用 Ff 将其强制指定*float类型。如果要将float数值强制指定为double类型,可以使用dD来记性转换,也可以不加。
如果需要时用float类型变量时,必须在数值的后边跟随f或F,否则编译器会直接将其作为double类型处理。

float a = 1.1f;
float b = 1.1F;
double c = 1.1d;
double d = 1.1D;
double e = 1.1;

4.1.3 浮点类型

布尔类型的值只能是 truefalse。布尔类型变量不能与其他类型之间进行转化。
在定义全局变量时,整数类型和浮点类型的默认值为 0 ,布尔类型的默认值为 false

4.2 引用类型

引用类型是构建C#应用程序的主要对象数据类型。在应用程序执行的过程中,预先定义的对象类型以new创建对象实例,并且储存在堆中。堆是一种系统以弹性配置的内存空间,没有特定大大小及存活时间,因此可以被弹性的运用于对象的访问。
引用类型就类似于生活中的代理商,代理商没有自己的产品,而是代理厂家的产品,使其就好像是自己的产品一样。
引用类型具有如下特征:

  1. 必须在托管堆中为引用类型变量分配内存。
  2. 使用new关键字来创建引用类型变量。
  3. 在托管堆中分配的每个对象都有与之相关联的附加成员,这些成员必须被初始化。
  4. 引用类型变量是由垃圾回收机制来管理的。
  5. 多个引用类型变量可以同时引用同一对象, 这种情况下对一个变量的操作会影响另一个变量所引用的同一对象。
  6. 引用类型被赋值前的值都是null。

所有被称为“类”的都是引用类型,主要包括类、接口、数组、委托

例:

using System;
namespace ConsoleApp1
{
    
    
    class Program
    {
    
    
        class C     
        {
    
    
            public int Value = 0;  
        }
        static void Main(string[] args)
        {
    
    
            int v1 = 0;
            int v2 = v1;
            v2 = 927;
            C c1 = new C();
            C c2 = c1;
            c2.Value = 112;
            Console.WriteLine("Values:{0},{1}", v1, v2);  			// 0 ,927
            Console.WriteLine("Refs:{0},{1}", c1.Value, c2.Value);  // 112  ,112
            Console.ReadLine();
        }
        
    }
}

5 值类型与引用类型的区别

从概念上看,值类型直接存储其值,而引用类型储存对其值得引用。这俩种类型储存在内存的不同地方。在C#中,必须在设计类型时就决定类型实例的行为。如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常。
从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。栈在编译是就分配好空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态的分配内存的大小。因此值类型总是在内存中占用一个预定义的字节数。而引用类型的变量则在堆中分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,即存放此变量实际值的地方。
也就是说值类型相当于现金,要用就直接用。而引用类型相当于存着,要用得先去银行取。
C#的所有值类型均隐式派生自System.ValueType,而System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals()方法,而对值类型按照实际的值来比较,而不是引用地址来比较。
下面以一段代码来展示值类型与引用类型的区别:

using System;
namespace ConsoleApp1
{
    
    
    class Program
    {
    
    
       
        static void Main(string[] args)
        {
    
    
            ReferenceAndValue.Demonstration();
            Console.ReadKey();
        }
    }
    public class stamp
    {
    
    
        public string Name {
    
     get; set; }
        public int Age {
    
     get; set; }
    }
    public static class ReferenceAndValue
    {
    
    
        public static void Demonstration()
        {
    
    
            stamp st1 = new stamp {
    
     Name = "张三", Age = 25 };
            stamp st2 = new stamp {
    
     Name = "李四", Age = 18 };
            int age = st1.Age;
            st1.Age = 22;
            stamp st3 = st2;
            st2.Name = "王五";
            Console.WriteLine("st1的年龄{0}",st1.Age);  // 22
            Console.WriteLine("年龄的值{0}",age);       // 25
            Console.WriteLine("st2的名字{0}",st2.Name); // 王五
            Console.WriteLine("st3的名字{0}",st3.Name); // 王五

        }
    }
}

6 枚举类型

枚举类型是一种独特的值类型,,它用于声明一种具有相同性质的常量。编写与日期相关的应用程序时,经常需要用到年、月、日、星期等日期数据,可以将这些数据组织成多个不同名称的枚举类型。使用枚举可以增加程序的可读性、可维护性。同时枚举类型可以避免类型错误。
在定义枚举类型时,如果不对其进行赋值,默认情况下,第一个枚举类型的值位0,后面每个枚举数的值依次递增1。
在C#中使用关键则enum类声明枚举,其形式如下:

enum 枚举名
{
    
    
	//枚举值名称 = 枚举值
	list1 = value1,
	list2 = value2,
	list3 = value3,
	...
	listN = valueN
}

例:

using System;
namespace ConsoleApp1
{
    
    
    class Program
    {
    
    
        enum MyDate
        {
    
    
            Sun = 0,
            Mon = 1,
            Tue = 2,
            Wed = 3,
            Thi = 4,
            Fri = 5,
            Sta = 6
        }
        static void Main(string[] args)
        {
    
    
            int k = (int)DateTime.Now.DayOfWeek;
            switch (k)
            {
    
    
                case (int)MyDate.Sun:
                    Console.WriteLine("今天是星期日");
                    break;
                case (int)MyDate.Mon:
                    Console.WriteLine("今天是星期一");
                    break;
                case (int)MyDate.Tue:
                    Console.WriteLine("今天是星期二");
                    break;
                case (int)MyDate.Wed:
                    Console.WriteLine("今天是星期三");
                    break;
                case (int)MyDate.Thi:
                    Console.WriteLine("今天是星期四");
                    break;
                case (int)MyDate.Fri:
                    Console.WriteLine("今天是星期五");
                    break;
                case (int)MyDate.Sta:
                    Console.WriteLine("今天是星期六");
                    break;

                default:
                    break;
            }
            Console.ReadKey();
        }
    }
}

7 类型转换

对于类型转换,就是用目标内存块去套取源内存中的数据,能套多少算多少。

7.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
uint long、ulong、float、double、decimal
char ushort、int、uint、long、ulong、float、double、decimal
float double
ulong float、double、decimal
long float、double、decimal

当一种类型的值转换为大小相等或更大的另一类型时,发生扩大转换。当一种类型的值转换为比较小的另一种类型时,则发生收缩转化。

7.2 显式转换

显式转换也可以称为强制转换,需要在代码中明确地声明要转换的类型。如果要把高精度的变量值赋值给低精度的变量,就需要使用显式转换。
下表列出了需要进行显式转换的数据类型:

源类型 目标类型
sbyte byte、ushort、unit、ulong、char
byte sbyte 、char
short sbyte、byte、ushort、unit、ulong、char
ushort sbyte、byte、short、char
int sbyte、byte、short、ushort、unit、ulong、char
uint sbyte、byte、short、ushort、int、char
char sbyte、byte、short
float sbyte、byte、short、ushort、int、uint、long、ulong、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、decimal

7.3 装箱和拆箱

将值类型转换为引用类型的过程叫做装箱,相反,将引用类型转换为值类型的过程叫做拆箱。在执行拆箱操作时,要符合类型一致的原则,否则会出现异常。
装箱是将一个值类型转换为一个对象类型(Object),而拆箱是将一个对象类型显式转换为一个值类型。对于装箱而言,它是将被装箱的值类型复制一个副本来转换。而对于拆箱而言,需要注意类型的兼容性,不能将一个值为string的object类型转换为int类型。
例:

using System;
namespace ConsoleApp1
{
    
    
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
            int a = 1;
            Object ob1 = new Object();  
            ob1 = a;        //装箱 将值类型转化引用类型

            string st1 = "张三";
            string st2 = "";
            Object ob2 = st1;
            st2 = (string)ob2;  //拆箱 将引用类型转换为值类型

            Console.WriteLine("ob1:{0}",ob1);   // 1
            Console.WriteLine("st2:{0}", st2);  //张三
            Console.ReadKey();
        }
    }
}

8 常量

常量就是值固定不变的量,而且常量的值在被编译时就已经确定。C#中用关键字const定义差常量,并且创建常量时必须设置初始值。常量就相当于每个公民的身份证号码,一点设置就不允许再修改。

猜你喜欢

转载自blog.csdn.net/qq_41525263/article/details/115362297