C#系列之值类型和引用类型

简介: C#系列之值类型和引用类型

前言


     这几天一直在思考这章讨论什么, 在上一章讨论string的时候牵涉到引用类型,那么我们这一章讨论讨论一下,值类型和引用类型。


     值类型和引用类型,它们的区别来源于传值方式。有人会认为值类型就存在栈上这是不一定的。详细看下文。


     有些人会说啊。。有垃圾回收机制进行清理内存。。不需要去折腾那么多吧 - -!。。。。。为了写好代码,避免面试问到。。还是勉为其难的讨论讨论吧。。。。。


值类型和栈


    栈,存储不是对象成员的值数据类型,还存放着局部变量,参数。


    那么他的工作原理是怎样的呢?首先要知道,数据在栈上,是从高内存位置往低内存位置填充的,变量地址不会重复的。


/

    假如有下面一段代码:


 231451049599186.png

231520179129382.png

   

     从上面可以看见,b代码块是嵌套a代码块里。由于代码从上到下的执行顺序,那么变量a会比变量b先入栈;可是b代码块会比a代码早结束,超出作用域之后,变量就会释放,因此,变量b会比变量a先释放。


231557504907307.png


231558000685414.png

    由此可见,灵活性并不高,如果希望生命活得长久点?这个时候,堆的作用就体现出来。

 

引用类型和堆


    堆,它的特性和栈有点相反,存储的是对象成员类型,是从低内存位置往高内存位置填充的。当值类型的变量为类型成员的时候,是与对象存放在堆里。


    先说下工作原理,有这样一段代码。

class Program
{
    static void Main(string[] args)
    {
        Human h;
        h = new Human();
    }
}


 

    首先,会在栈上分配一个空间,存放引用h,它仅仅是一个引用,不是对象。到第二句进行实例化对象,new 运算符是用来请求分配储存空间的,CLR会搜索堆上足够的位置,分配给对象,然后new会返回它所在堆上的地址给引用。因此在栈上存放着该引用指向堆上的对象的地址


综上所述:


    值类型的使用减少了堆的压力,同时减少垃圾回收的次数。引用类型却弥补了生命周期的不足,增加了灵活性。


    值类型创建变量时是赋予默认值的,例如int默认值是0。而引用类型创建变量,默认是null。那么,没有对象的引用类型的变量使用时会报异常NullReferenceException。


    值类型的变量是以复制的方式赋值,执行一次逐字段的复制,而引用类型将对象在堆上的地址赋于新变量进行引用。


    下面有段代码充分说明了引用类型和值类型的区别 :(借用Clr C#的例子)

struct Struct//值类型
{
    public int x;
}
class Class //引用类型
{
    public int x;
}
class Program
{
    static void Main(string[] args)
    {
        //代码A
        Struct s1 = new Struct();  //分配在栈上
         Class c1 = new Class();    //分配在堆上
         s1.x = 1;
        c1.x = 1;
        Console.WriteLine(s1.x);  //输出1 
        Console.WriteLine(c1.x);  //输出1
        //代码B
        Struct s2 = s1;           //复制栈上成员给s2
        Class c2 = c1;            //复制引用给c2
        s2.x = 2;                 //值类型,s1.x不变,s2.x 变更
         c2.x = 2;                 //引用类型,c1.x和c2.x 同时改变
         Console.WriteLine(s1.x);  //1 值类型
         Console.WriteLine(s2.x);  //2 值类型
         Console.WriteLine(c1.x);  //2 引用类型
         Console.WriteLine(c2.x);  //2 引用类型
    }
}


  c1将地址复制给c2,也就是说c1和c2指向的是同一个对象,因此c1和c2其中一个修改了,另外的也会受影响。


  s1将成员复制给s2,虽然s1和s2存储了相同的值,但是他们内存地址都不相同,存的是属于自己的值,因此s1和s2其实一个修改了,也不会影响另外一个。

目录
相关文章
|
7月前
|
存储 C# C语言
C# OOP之五 深入理解值类型和引用类型
C# OOP之五 深入理解值类型和引用类型
26 0
|
3月前
|
安全 编译器 C#
C#中的可空引用类型:减少空引用异常的利器
【1月更文挑战第9天】C# 8.0中引入的可空引用类型特性,它通过在编译时提供更精确的静态分析,帮助开发者减少运行时的空引用异常。文章详细阐述了可空引用类型的工作原理、如何配置项目以使用此特性,以及在实际编码中如何利用可空引用类型提升代码的健壮性和可读性。
|
8月前
|
存储 C# 图形学
代码解析 C# 引用类型还是值类型
代码解析 C# 引用类型还是值类型
|
4月前
|
存储 C#
C# “值类型“和“引用类型“在内存的分配
C# “值类型“和“引用类型“在内存的分配
|
7月前
|
C#
C#由Dictionary赋值引发的对引用类型使用的思考
C#由Dictionary赋值引发的对引用类型使用的思考
|
安全 编译器 C#
30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
85 0
30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
|
编译器 C#
表达式树练习实践:C#值类型、 引用类型、泛型、集合、调用函数
表达式树练习实践:C#值类型、 引用类型、泛型、集合、调用函数
138 0
|
存储 C#
C# 值类型与引用类型 null与可空类型
本文目录 1. 值类型与引用类型 2. null的含义 3. 可空类型
160 0
|
存储 Java 程序员
C#基础——值类型和引用类型
C#基础——值类型和引用类型
550 0
C#基础——值类型和引用类型
|
1月前
|
C#
24. C# 编程:用户设定敌人初始血值的实现
24. C# 编程:用户设定敌人初始血值的实现
18 0