C#里面把数据类型分为两大类,分别为值类型和引用类型,值类型包括基本数据类型(int ,double等),结构和枚举,,,引用类型包括接口,数组,Object类型,类,委托,字符串,null类型等,那这两大类有什么区别呢?
1.值类型:就是一个包含实际数据的量。即当定义一个值类型的变量时,C#会根据它所声明的类型,以栈方式分配一块大小相适应的存储区域给这个变量,随后对这个变量的读或写操作就直接在这块内存区域进行
2.引用类型:一个引用类型的变量不存储它们所代表的实际数据,而是存储实际数据的引用。
引用类型分两步创建:首先在栈上创建一个引用变量,然后在堆上创建对象本身,再把这个内存的句柄(也是内存的首地址)赋给引用变量。
相信大家已经对值类型和引用类型有了一定的掌握了吧,接下来让我们看一个例子巩固一下
namespace 值类型和引用类型的区别
{
public class Car
{
public int speed { get; set; }
public string carName { get; set; }
public Car(int speed, string carName)
{
this.speed = speed; this.carName = carName;
}
}
public class Program
{
static void Main(string[] args)
{
Car a = new Car(100, "宝马");
Car b = new Car(200, "奔驰");
int myspeed = a.speed;//测试值类型
a.speed = 150;
Car c = b;//测试引用类型
b.carName = "法拉利";
Console.WriteLine("myspeed={0}", myspeed);
Console.WriteLine("a.speed={0}", a.speed);
Console.WriteLine("b.carName={0}",b.carName);
Console.WriteLine("c.carName={0}", c.carName);
}
}
}运行结果如下:
int myspeed=a.speed,a.speed=150,这里申请了一个int型的变量myspeed,它在栈中另开辟一个地址,把值存在其中,而a.speed是原先的值没变;
Car c=b;这是把c指向b,也就是说两者在栈中都存的是同一个引用,当b.carName改变时,c里面的值也会改变,结合上面的图解,大家应该明白了吧
3.特殊引用类型String
下面看一个例子:
String a="111";
String b=a;
a="222";
Console.WriteLine(a);//输出a的值为222;
Console.WriteLine(b);//输出b的值为111
我们如果按照之前讲的会误以为string值类型,其实不然,当a="222"时,事实上是a=new string("222"),也就是说新分配了一个引用给a,把之前的a给覆盖了,大家明白了吧
下面来总结一下:
1. 值类型的数据存储在内存的栈中;引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址。
2. 值类型存取速度快,引用类型存取速度慢。
3. 值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用
4. 值类型继承自System.ValueType,引用类型继承自System.Object
5. 栈的内存分配是自动释放;而堆在.NET中会有GC(垃圾回收)来释放