zoukankan      html  css  js  c++  java
  • 深入理解类型

    什么是值类型和引用类型

    • 值类型在线程栈分配空间,引用类型在托管堆分配空间

    值类型与引用类型的区别

    • 两类型的数据存储位置不同
    • 在引用类型中嵌套值类型时,或者在值类型装箱的情况下,值类型的实例就会被分配到托管堆上
    • 值类型继承自ValueType,ValueType又继承自System.Object;而引用类型则直接继承于System.Object;
    • 值类型的内存不受GC控制,作用域结束时,值类型会被操作系统自行释放
    • 若值类型为密封的(sealed),你将不能把值类型作为其他任何类型的基类;而引用类型则一般具有继承性,这里是指接口和类;
    • 值类型不能为null值,它会被默认初始化为该值类型的默认值;而引用类型默认会初始化为null值,表示不指向托管堆中的任何地址;对值为null的引用类型的任何操作都会引发NullRefernceException异常
    • 由于值类型变量包含其实际数据,因此默认情况下,值类型之间的参数传递不会影响变量本身;而引用类型变量保存的是数据的引用地址,它们作为参数传递时,参数会发生改变,从而影响引用类型变量的值

    几种类型嵌套情况

    • 引用类型中嵌套定义值类型
      • 如果类的字段类型是值类型,它将作为引用类型实例的一部分,被分配到托管堆中,但那些作为局部变量(如下代码中的c变量)的值类型,则仍然会被分配到线程堆栈中.
      • 代码示例
        //引用类型嵌套定义值类型的情况
        public class NestedValueTypeInRef
        {
            //valuetype作为引用类型的一部分被分配到托管堆上
            private int valuetype = 3;
            public void method()
            {
                //C被分配到线程堆栈上
                char c = 'c';
            }
        }
        class Program
        {
    
            static void Main(string[] args)
            {
    
                NestedValueTypeInRef typeInRef = new NestedValueTypeInRef();
            }
        }
    
    - 示例图
    
    ![引用嵌套值类型.png](https://upload-images.jianshu.io/upload_images/2981616-3a77c91cee879a03.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/240)
    
    • 值类型中嵌套定义引用类型

      • 堆栈上将保存该引用类型的引用,而实际的数据则依然保存在托管堆中
      • 代码示例
       public class TestClass
      {
          public int x;
          public int y;
      }
      class Program
      {
          //值类型嵌套定义引用类型的情况
          public struct NestedRefTypeInValue
          {
              //结构体字段,注意,结构中的字段不能被初始化
              private TestClass classinValuetype;
      
              //结构体中的构造函数,注意,结构体中不能定义无参的构造函数
      
              public NestedRefTypeInValue(TestClass t)
              {
                  if (t==null)
                  {
                      throw new ArgumentNullException("t");
                  }
                  classinValuetype = t;
                  classinValuetype.x = 3;
                  classinValuetype.x = 5;
      
              }
          }
          static void Main(string[] args)
          {
              //值类型变量
              NestedRefTypeInValue typeInValue = new NestedRefTypeInValue(new TestClass());
          }
      }
      
      • 示例图

      值类型嵌套引用类型.png

    两大类型间的转换------装箱与拆箱

    • 值类型转换为引用类型称为装箱,引用类型转换为值类型称为拆箱

    • 隐式转换;由低级别类型向高级别类型的转换过程(例如子类隐式转换为父类)

    • 显式转换(也称为强制类型转换);这种转换可能会导致精度损失或者出现运行时异常;

      • 转换格式
      (type)(变量,或函数);
      
    • 通过isas运算符进行安全的类型转换;

    • 示例从内存角度对装箱,拆箱进行深入分析

      • 代码示例
      int i=3;
      //装箱
      object o=i;
      //拆箱
      int y=(int)o;
      
      • 装箱步骤:
        • 1,内存分配:在托管堆中分配好内存空间以存放复制的实际数据;
        • 2,完成实际数据的复制:将值类型实例的实际数据复制到新分配的内存中
        • 3,地址返回:将托管堆中的对象地址返回给引用类型的变量
      • 装箱示例图
        装箱过程.png
      • 拆箱步骤:
        • 1,检查实例:首先检查要进行拆箱操作的引用类型变量是否为null,如果为null则抛出异常;反之则检查变量是否和拆箱后的类型是同一类型,若为否,会导致InvalidCasetException异常;
        • 2,地址返回:返回已装箱的实际数据部分的地址
        • 3,数据复制:将托管堆中的实际数据复制到栈中
      • 拆箱示例图
        装箱过程.png

    参数传递问题剖析

    参数可分为形参和实参两种.形参指的是被调用方法中的参数,也就是方法中定义的参数;实参指的是调用方法时,传递给对应参数的值;

    static void Main(string[] args)
    {
        int addNum=1;
        //addNum 就是实参
        Add(addNum);
    }
    //addnum就是形参
    private static void Add(int addnum)
    {
        ........
    }
    
    
    • 值类型参数的按值传递
      • 传递的是该值类型实例的一个副本,因此方法中对参数的改变不会影响到实参
    • 引用类型参数的按值传递
      • 当传递的参数是引用类型时,传递和操作的目标是指向对象的地址,而传递的内容是对象地址的复制.由于地址指向的是实参的值,方法对地址进行操作时,实际上操作了地址所指向的值,所以调用方法后原来实参的值就会被修改
      • string具有不可变性,因此不会改变; 这是一特殊情况
    • 值类型,引用类型参数的按引用传递
      • 使用ref,out关键字来实现参数的传递都是引用传递
  • 相关阅读:
    HTB-靶机-Charon
    第一篇Active Directory疑难解答概述(1)
    Outlook Web App 客户端超时设置
    【Troubleshooting Case】Exchange Server 组件状态应用排错?
    【Troubleshooting Case】Unable to delete Exchange database?
    Exchange Server 2007的即将生命周期,您的计划是?
    "the hypervisor is not running" 故障
    Exchange 2016 体系结构
    USB PE
    10 months then free? 10个月,然后自由
  • 原文地址:https://www.cnblogs.com/youMo/p/10360404.html
Copyright © 2011-2022 走看看