zoukankan      html  css  js  c++  java
  • C# 装箱 与 拆箱

    1、使用场景

    装箱的使用场景:想把值类型当做引用类型来使用,于是把值类型转换为引用类型。

    拆箱的使用场景:想把引用类型当做值类型来使用,于是把引用类型转化为值类型。

    再进一步,为什么想把值类型当做引用类型来使用? 比如:方法定义时接受Object 类型的参数,而你想传递int 类型,此时需要把int装箱为Object;对于一些非泛型的容器,为了保证通用,元素类型定义为Object,此时向容器内添加int,double的时候,需要装箱。

    为什么想把引用类型当做值类型来使用呢?对于值类型装箱后的引用类型,你想直接使用值类型的数据。

    2、实现原理

    装箱:

    (1)在堆上分配一块内存,该内存就是一个实例

    (2)将值类型的数据复制到刚创建的实例中

    (3)返回该实例的引用

    拆箱:

    (1)取出实例中的数据

    (2)赋值给新的变量

    3、辨别是否进行了装箱拆箱

    拆箱是显式的,而装箱可以显式也可以隐式,关键是判断有没有把值类型当做引用类型来使用。 

    View Code
     1 class Program
    2 {
    3 static void Main()
    4 {
    5 int a = 123;
    6
    7 // 显示的装箱,也可以认为是向上转型,是安全的。
    8        //int(Int32)继承ValueType,ValueType 继承Object
    9 object obj = a;

    10
    11 // 隐式的装箱,Int32是struct(值类型)
    12      // Int32本身没有GetType方法,而是继承了Object的GetType方法。
    13 Type type = a.GetType();

    14
    15 // 没有装箱,Int32是struct(值类型),重写了Object的ToString方法,
    16 // a.ToString() 调用Int32 上的方法
    17 string s = a.ToString();

    18
    19 // 显式的拆箱
    20 int b = (int)obj;

    21 }
    22 }

    4、尽量避免装箱拆箱

    为什么?因为装箱拆箱耗费时间和空间。

    如何避免?

    (1)对于方法定义接受的参数为object的情况,过载一个方法,接受的参数为值类型。

    (2)对于非泛型的容器,采用泛型容器代替。

    5、如何修改已装箱的值类型

    举例来说:

    View Code
     1 class Program
    2 {
    3 static void Main()
    4 {
    5 MyStruct myStruct = new MyStruct();
    6 myStruct.a = 100;
    7
    8 object obj = myStruct;
    9 ((MyStruct)obj).Modify();
    10 }
    11 }
    12
    13 struct MyStruct
    14 {
    15 public int a;
    16 public void Modify()
    17 {
    18 this.a = 200;
    19 }
    20 }

    1、对于已经装箱的obj,如果要修改内容,需要调用MyStruct的方法,因此就要把obj转化为struct,也就是拆箱。

    2、拆箱后,会在栈上生成新的实例,调用方法不会影响obj。

    也就是说,拆箱会在栈上产生新的实例,对栈实例的修改不会影响到原来的obj。

    解决办法:人为干涉,不让obj进行拆箱操作。

    让MyStruct实现接口IModify,在接口IModify中声明Modify方法,将obj 转型为 接口,这时候并没有进行拆箱,修改会产生副作用。如下:

    View Code
     1 class Program
    2 {
    3 static void Main()
    4 {
    5 MyStruct myStruct = new MyStruct();
    6 myStruct.a = 100;
    7
    8 object obj = myStruct;
    9 ((IModify)obj).Modify();
    10 }
    11 }
    12
    13 struct MyStruct:IModify
    14 {
    15 public int a;
    16 public void Modify()
    17 {
    18 this.a = 200;
    19 }
    20 }
    21
    22 public interface IModify
    23 {
    24 void Modify();
    25 }
  • 相关阅读:
    L1-031 到底是不是太胖了
    L1-030 一帮一
    PyCharm--git配置
    websocket--python
    UDP--python
    TCP--python
    pytest--metadata
    pytest--xdist
    pytest--夹具
    pytest--变量
  • 原文地址:https://www.cnblogs.com/nzbbody/p/2319144.html
Copyright © 2011-2022 走看看