zoukankan      html  css  js  c++  java
  • C#---值类型为什么不能为空null




    参考博客:
    shyleoking

    前言

    首先我们知道值类型存储在栈(Stack)中,而引用类型存储在堆(Heap)中,栈的工作方式是先进后出,会保证先分配内存的变量后释放。
    这样就保证了栈中先进后出的规则不与变量的生命周期起冲突。

    值类型的生命周期

    在C#中,对变量的声明要求是先定义后使用,变量的生命周期是从其定义开始直到程序的控制离开该变量所在的大括号{ }

    static void Main(string[] args)
    {
        int k = 10;//k的生命周期开始了
    
        for (int i = 0; i <= 10 - 1; i++)//i的生命周期开始了
        {
            int m = k + i;//m的生命周期开始了
    
            for (int j = i; j <= 10 - 1; j++)//j的生命周期开始了
            {
                int n = j * i;//n的生命周期开始了
                //n的生命周期结束了
                
            }//j的生命周期结束了
    
            //m的生命周期结束了
            
        }//i的生命周期结束了
    
        //k的生命周期结束了
    }
    

    下面的图描述了这些变量的生命周期和堆栈的存储

    把值类型设置为null的情况

    上述的代码改为如下形式:

    static void Main(string[] args)
    {
        int k = 10;//k的生命周期开始了
    
        for (int i = 0; i <= 10 - 1; i++)//i的生命周期开始了
        {
            int m = k + i;//m的生命周期开始了
            k = null; //k的生命周期结束了???
    
            //m的生命周期结束了
    
        }//i的生命周期结束了
    
        //k的生命周期结束了
    }
    

    现在我们看下代码到第8行时的栈:

    这个时候k在栈底,如果我们想释放k,就要先释放m和i。
    所以这样操作就破坏了栈的先进后出的规则,所以会出错,编辑就会报错。

    引用类型为什么可以设置为null

    上述的代码改为如下形式:

    static void Main(string[] args)
    {
        List<int> k = new List<int>();//k的生命周期开始了
    
        for (int i = 0; i <= 10 - 1; i++)//i的生命周期开始了
        {
            k.Add(i);
    
            int m = k.Count;//m的生命周期开始了
    
            for (int j = i; j <= 10 - 1; j++)//j的生命周期开始了
            {
                int n = j * i;//n的生命周期开始了
    
                //n的生命周期结束了
    
            }//j的生命周期结束了
    
            //m的生命周期结束了
    
        }//i的生命周期结束了
    
        //k的生命周期结束了
    }
    

    栈中的处理大致如图:

    此时变量k还是分配在栈中,但实际存放List实例的区域是在堆中。对List的实例使用,是通过在栈中的变量k来间接的指向的。所以就把对象引用null和生命周期两个概念可以分离出来。

    所以就算我们把k = null,也只是让变量k不再指向堆中的有效地址了,但其生命周期并没有发生变化。

    现在我们明白了,因为值类型变量直接在栈中保存了数据,因此在生命周期结束前数据不能被任何形式的销毁,而引用类型变量在堆中保存数据,所以赋值null其实是将对应在堆中的数据销毁而不是结束变量的生命周期。

  • 相关阅读:
    设计模式(一)工厂模式Factory(创建型)
    c++ 依据输入动态声明数组(一维,二维)
    【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)
    正确的 zip 压缩与解压代码
    站点设计高性能高并发
    hdu 1712 ACboy needs your help 分组背包
    17周 oj 比較大小 类模板
    并行编程之多线程共享非volatile变量,会不会可能导致线程while死循环
    数据库升级ora-04063 DBMS_REGISTRY has error
    对软件体系结构的认识
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/14212505.html
Copyright © 2011-2022 走看看