聊聊C#的值类型和引用类型

        在C#中,变量的类型分为两种:值类型和引用类型

        不管是在学生时期,还是在职业生涯中,这个问题都是最基本的概念,也几乎在实际使用过程中不会涉及到。但是却是各种考试、各种面试都会提及的问题。

        这里根据个人的经验,谈谈对值类型和引用类型的理解。

一、基本概念

什么是值类型,什么是引用类型

概念:值类型直接存储其值,而引用类型存储对其值的引用。

值类型包括:byte,short,int,long,float,double,decimal,char,bool 和 struct 

引用类型包括: class、interface、deleggate、object、数组和string

值类型和引用类型的区别如下: 

  • 值类型变量声明后,不管是否已经赋值,编译器为其分配内存。
  • 引用类型当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。
  • 值类型的实例通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中。
  • 引用类型的对象总是在进程堆中分配(动态分配)

 二、值类型和引用类型在内存中的部署

        经常听说,并且经常在书上看到:值类型部署在栈上,引用类型部署在托管堆上。实际上并没有这么简单。MSDN上说:托管堆上部署了所有引用类型。这很容易理解。当创建一个应用类型变量时:

object reference = new object();

        关键字new将在托管堆上分配内存空间,并返回一个该内存空间的地址。左边的reference位于栈上,是一个引用,存储着一个内存地址;而这个地址指向的内存(位于托管堆)里存储着其内容(一个System.Object的实例)。 

        综上所述:

        当声明一个引用类型时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。

        值类型变量声明后,不管是否已经赋值,编译器为其在栈中分配内存。

三、值类型和引用类型实例解析

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Dowork();
        }

        static void Dowork()
        {
            int i = 0;  // int 是值类型
            Console.WriteLine(i);   // i = 0
            Pass.value(i);          // 值类型使用的是 i 的副本,i不变
            Console.WriteLine(i);   // i = 0
            WrappendInt wi = new WrappendInt(); // 创建类 WrappendInt 的另外一个实例
            Console.WriteLine(wi.Number);   // 0 // 被默认构造器初始化为 0
            Pass.Reference(wi);     // 调用方法,wi 和 param 将引用同一个对象
            Console.WriteLine(wi.Number);   // 42
        }
    }

    class Pass
    {
        public static void value(int param)
        {
            param = 42; // 赋值操作使用的是值类型参数的一个副本,原始参数不受影响
        }

        public static void Reference(WrappendInt param) // 创建类 WrappendInt 的一个实例
        {
            param.Number = 42;  // 此参数是引用类型的参数
        }

    }

    class WrappendInt   // 类是引用类型
    {
        public int Number;
    }
}

小结:

        c#的值类型是为变量在栈上分配了一块内存,用于存储数据,而引用类型分为两部分,声明时只在栈上分配了一小部分内存,堆上没分配,而new引用变量时,是在堆上分配了一块内存,存储的是栈上的内存地址,注意:struct是值类型,string和class是引用类型,string不需要new是因为想要语义化“字符串”省略创建过程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MarcoPro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值