解析C#中的值类型和引用类型

文章将会以一种比较通俗易懂的方式讲得让一些C#新入门学者可以看懂。
当我们提到C#的内存管理机制,就不得不联想到其最基础的引用类型和值类型,那么什么是引用类型,什么是值类型呢。
在这里插入图片描述
1、值类型声明变量之后,不管是否赋值,内存都会为其在栈空间分配一块内存。
2、值类型通常是分配在线程栈上,但是某些情况下,值类型也可以存储在托管堆1中。
3、当声明一个类时,系统只会在栈中分配一块很小的内存给它,而此时并没有为其分配堆上的空间。只有当使用new时,才把为其分配堆上的空间,并返回堆上的空间至栈上。

这里很多同学可能会有疑问,为什么string是引用类型呢`

string a = A;
string b = a;
a=B;
Consloe.WriteLine("a={0}\tb={1}\t",a,b);

此时输出的结果为a=B,而b=a。
这很像值类型对不对,但实际上,这是由于运算符的重构所导致的结果。当a被重新赋值时,.NET为a在托管堆上重新分配了一块内存。这样做的目的是,使字符串类型与通俗意义上讲的字符串更接地气。

接下来我们来从最基础的层面来分析应用类型和值类型。

一、一切皆是类型
也许会疑问,类不都是引用类型吗,那值类型又是什么。

引用类型和值类型都继承自System.Object类。不同的是,几乎所有的引用类型都直接从System.Object继承,而值类型则继承其子类,即 直接继承System.ValueType。System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。

二、谬论
经常听说,并且经常在书上看到:值类型部署在栈上,引用类型部署在托管堆上。实际上并没有这么简单。或者说这种说法是不严谨的。

下面我先以数组作为例子:

int [] a = new int  [100]

数组是引用类型,而其元素int均是值类型。那么数组中的元素是储存在栈上还是储存在堆里呢。
其实这些元素是储存在堆里边的,其储存方式见下图。
在这里插入图片描述
用new为数组a在堆上分配了一块内存,这块内存的大小相当于100个int。这块内存是一次分配的,所以就等效于在堆中建立了一个堆中栈。

a[1]=2;
id(a);
a[1]=3;
id(a);\\id为返回地址的函数

我们用id返回a改变后的地址,发现与a之前的地址是一模一样的。

接下来我们再看二维数组

int[,] b = new int [100,100]

其在内存中的存储方式是这样的
在这里插入图片描述
当声明并new b后,系统在堆中为b分配了100块内存,这些内存并不是连在一起的,数组个元素(一维数组)指向的是空值,当为某个元素赋值之后,其就会像上边一维数组一样,在堆中建立一个类似于栈的空间。

由此对数组我们可以总结出以下的规律

sometype[] a =new sometype[100];

如果sometype是值类型,则会一次在托管堆上为100个值类型的元素分配存储空间,并自动初始化这100个元素,将这100个元素存储到这块内存里。

如果somtype是引用类型,则会先在托管堆为testTypes分配一次空间,并且这时不会自动初始化任何元素(即sometype[i]均为null)。等到以后有代码初始化某个元素的时候,这个引用类型元素的存储空间才会被分配在托管堆上。

参考文献

今天终于上到这一部分内容啦,马上来补一点笔记


        public static void ChangValue(Person p)
        {
            p = new Person();
            p.Name = "Mike";
        }
        static void Main(string[] args)
        {

            Person p = new Person();
            p.Name = "John";
            ChangValue(p);
            Console.WriteLine("}", p.Name);
                
        }

得到的输出的是“John”
这里是返回的是p输入的地址;而不是p改变后的地址

 public static void ChangValue( ref Person p)

如果代码改成这样则是输出“Mike”

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值