一、总的区别

值类型                                             引用类型
内存分配地点                                      分配在栈中                                      分配在堆中
效率                                                   效率高,不需要地址转换                   效率低,需要进行地址转换
内存回收                                            使用完后,立即回收                          使用完后,不是立即回收,等待GC回收
赋值操作                                            进行复制,创建一个同值新对象          只是对原有对象的引用
函数参数与返回值                               是对象的复制                                     是原有对象的引用,并不产生新的对象
类型扩展                                            不易扩展                                            容易扩展,方便与类型扩展

二、赋值区别

static void Main(string arg[])  
{  
    int x = 10;  
    int y = x;  
    Console.WriteLine(x.ToString() + "," + y.ToString());//输出的结果是:10,10  
    y = 20;  
    Console.WriteLine(x.ToString() + "," + y.ToString());//输出的结果是:10,20  
    int[] arry = new int[1];  
    int[] arry1 = arry;  
    arry[0] = 10;  
    Console.WriteLine(arry[0].ToString() + "," + arry1[0].ToString());//输出的结果是:10,10  
    arry1[0] = 20;  
    Console.WriteLine(arry[0].ToString() + "," + arry1[0].ToString());//输出的结果是:10,20  
    string str1 = "liao";  
    string str2 = str1;  
    Console.WriteLine(str1 + "," + str2);//输出的结果是:liao,liao  
    str1 = "xiao";  
    Console.WriteLine(str1 + "," + str2);//输出的结果是:xiao,liao  

        static void Main(string arg[])
        {
            int x = 10;
            int y = x;
            Console.WriteLine(x.ToString() + "," + y.ToString());//输出的结果是:10,10
            y = 20;
            Console.WriteLine(x.ToString() + "," + y.ToString());//输出的结果是:10,20
            int[] arry = new int[1];
            int[] arry1 = arry;
            arry[0] = 10;
            Console.WriteLine(arry[0].ToString() + "," + arry1[0].ToString());//输出的结果是:10,10
            arry1[0] = 20;
            Console.WriteLine(arry[0].ToString() + "," + arry1[0].ToString());//输出的结果是:10,20
            string str1 = "liao";
            string str2 = str1;
            Console.WriteLine(str1 + "," + str2);//输出的结果是:liao,liao
            str1 = "xiao";
            Console.WriteLine(str1 + "," + str2);//输出的结果是:xiao,liao
        }

1、因int 是值类型,int x  int y 内存中就有两个地方存储x,y;所以当改变x或y的值时,都不会改变另一个变量的值。
2、因int [] arry,int []arry1 是数组,数组是引用类型,所以这两个变量引用了同一个对象(数组)
所以当 改变某一个引用指向的对象的属性同时也会影响到所有其他指向这个对象的引用,所以当arry1[0]的值改成20时,arry[0]的值也随着改变成20;最后的arry[0]和arry[1]的值都为20;不过虽然字符类型string也是引用类型,但它的工作方式更像值类型,既当str1的值改成"xiao"时,新创建了一个string对象,str1引用这个新的string对象;str2仍然引用原来string对象。产生这种行为的原因是string对象是恒定的,也就是说,一旦一个string对象被创建,它的值就不能再修改,所以当改变一个字符串变量的值的时候,仅仅是新创建了一个包含修改内容的新的string对象。
三、作为函数参数或者返回值

class Program  
{  
    public static void add(int k)  
    {  
        k = k + 39;  
    }  
 
    public static void add(ref int i)  
    {  
        i = i + 39;  
 
    }  
 
    public static void add(int[] j)  
    {  
        j[0] = j[0] + 39;  
    }  
 
    public static void astr(ref string sy)  
    {  
        sy = "ddd";  
    }  
 
    static void Main(string[] args)  
    {  
        int[] ary = new int[1];  
        int[] ary1 = ary;  
        ary[0] = 1;  
        add(ary[0]);  
        Console.WriteLine(ary[0].ToString()); //输出的结果是:1  
        add(ref ary[0]);  
        Console.WriteLine(ary[0].ToString()); //输出的结果是:40  
        add(ary);  
        Console.WriteLine(ary[0].ToString()); //输出的结果是:79  
        string str4 = "liaoxiaol";  
        astr(ref str4);                 //输出的结果是:ddd //str4的值已改变  
        Console.WriteLine(str4);  
    }  

        class Program
        {
            public static void add(int k)
            {
                k = k + 39;
            }

public static void add(ref int i)
            {
                i = i + 39;

}

public static void add(int[] j)
            {
                j[0] = j[0] + 39;
            }

public static void astr(ref string sy)
            {
                sy = "ddd";
            }

static void Main(string[] args)
            {
                int[] ary = new int[1];
                int[] ary1 = ary;
                ary[0] = 1;
                add(ary[0]);
                Console.WriteLine(ary[0].ToString()); //输出的结果是:1
                add(ref ary[0]);
                Console.WriteLine(ary[0].ToString()); //输出的结果是:40
                add(ary);
                Console.WriteLine(ary[0].ToString()); //输出的结果是:79
                string str4 = "liaoxiaol";
                astr(ref str4);                 //输出的结果是:ddd //str4的值已改变
                Console.WriteLine(str4);
            }
        }

说明:
1、对于值类型的变量:要想在函数中对传进去的参数做真正的修改,需要借助于ref这个关键字,所以当执行add(ary[0])后,arry[0]的值时并没有改变;而当执行add(ref ary[0])后,ary[0]的值,就变成了1+39=40;
2、对于引用类型的变量,则和值变量相反;而在实际应用中我们并不想引用类型变量作为函数参数传入后,其值有所心改变,要做到这一点需要为“引用类型”提供一个额外的clone函数,所以当执行add(arry)后,arry[0]的值就变成了40+39=79;
3、虽然string类型也是引用类型但前面也说过string 类型的工作更像值类型。

附加:
对于引用类型来说,提供一个clone函数不是一件容易的事情,尤其出现引用类型嵌套的时候,在C#中,尤其自己定义类型的时候,常常由于是用struct来定义还是用class来定义,即是定义一个值类型还是一个引用类型呢。在这本书上给了几个判定条件,如果如下几点都满足的话,建议用struct来定义为值类型,否则用class定义为引用类型。

1、这个类型是否主要为了数据存储;
2、是否只通过属性来访问对象的数据成员;
3、这个类型是否不会有子类型;
4、在程序处理的时候不会把这个类型对象通过多态来处理。
总而言之,在C#中,就是把底层面的数据用值类型来处理,而包含复杂操作,需要进行扩展的数据用引用类型来处理。

转载于:https://www.cnblogs.com/sntetwt/archive/2011/05/23/2054776.html

6. 区别值类型和引用类型。相关推荐

  1. golang值类型与引用类型的区别

    1.golang值类型与引用类型的区别 1.1 本质存储区别 值类型与引用类型的区别主要在于: 值类型的变量: 存储当前类型的存储的数据.值类型包括数值类型.bool.string.数组.struct ...

  2. golang中的值类型和引用类型

    值类型与引用类型 不管是Java还是golang中,都有值类型和引用类型的概念.在使用两者时,发现这两种语言之间还是有差异的. 值类型 值类型:这些类型的变量直接指向存在内存中的值,值类型的变量的值存 ...

  3. 值类型与引用类型的区别

    可以这样理解: 值类型保存的是具体的值 引用类型保存的是值的地址 例如 int a = 1; int b = a; b++; 这时b为2,a仍然是1 再看引用类型,例如有个类型是 User User ...

  4. java引用类型和值类型_[Java教程]JavaScript中值类型和引用类型的区别

    [Java教程]JavaScript中值类型和引用类型的区别 0 2017-02-24 00:00:35 JavaScript的数据类型分为两类:原始类型和对象类型.其中,原始类型包括:数字.字符串和 ...

  5. 值类型与引用类型比较与区别

    在.NET中或许我们不用担心内存管理以及垃圾回收器(Garbage Collection GC)的问题,但是我们还是应该了解这些东东以便在必要的时候优化我们程序的性能.而且,如果对内存管理如何工作有所 ...

  6. Golang的值类型和引用类型的范围、存储区域、区别

    常见的值类型和引用类型分别有哪些? 值类型:基本数据类型 int 系列, float 系列, bool, string .数组和结构体struct,使用这些类型的变量直接指向存在内存中的值,值类型的变 ...

  7. swift string转int_swift中结构体和类的区别(值类型和引用类型的区别)

    在swift中结构体和类有着更多的相同之处,在一般的使用中能够做到互相替换.我们可以先看看官方文档的描述: Unlike other programming languages, Swift does ...

  8. C#类和接口、虚方法和抽象方法及值类型和引用类型的区别

    1.C#类和接口的区别 接口是负责功能的定义,项目中通过接口来规范类,操作类以及抽象类的概念! 而类是负责功能的具体实现! 在类中也有抽象类的定义,抽象类与接口的区别在于: 抽象类是一个不完全的类,类 ...

  9. 值类型和引用类型的区别

    一.定义 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值,那么调用这个方法是传入的变量的值也将改变. 值类型表示复制一个当前变量传给方法,当你 ...

最新文章

  1. Binary XML file line #39: 最多只支持3个子View,Most only support three sub vi
  2. 闲鱼单体应用Serverless化拆分实践
  3. 计算机系统覆盖,计算机系统软件顶会OSDI 2021最佳论文出炉,邢波团队研究入选...
  4. BigData:绘制2018年福布斯中国富豪榜人根据出生地绘制个人或其家族财富分布热点图
  5. 企业发展步入“新两化” 用友优普助力中型企业商业创新
  6. IP子网编址和无类域路由CIDR
  7. cuteEditor6.0多语言版(集成lic文件)
  8. 10.深入分布式缓存:从原理到实践 --- EVCache探秘
  9. mysql统计某一个数据库中有几张表
  10. 系泊系统悬链线matlab,基于悬链线方程的系泊系统状态分析
  11. windows 10 下载工具
  12. word表格删除空白行java_在Word中怎样批量删除空行,这些点主要注意
  13. 连接数据库失败,难道MySQL 5.7客户端与8.0数据库不兼容?
  14. 历年诺贝尔生理学或医学奖
  15. 用谷歌按钮登录_使用非常简单的设置即可登录Google的按钮
  16. android开发--mp3播放器项目源代码(xml文件解析,.lrc,.mp3文件下载,同时显示歌词)
  17. centos7上安装rar解压软件
  18. Mysql出租车轨迹的分析_一种基于出租车轨迹数据的交通出行共现现象的可视化分析方法与流程...
  19. kotlin协程与线程池
  20. 使用yum info查看软件包信息与常用软件包

热门文章

  1. 同样是做冻品生意,哪类人更挣Q?
  2. 旅游捞金的六大方式,玩着把钱赚了
  3. 耍小聪明的人,永远不可能取得自己事业的成功
  4. 华硕固件,梅林固件,高恪固件等等有什么区别?
  5. 帆软报表 js 调用sql_SQL Server中的报表–创建由先前创建的主报表调用的基于矩阵的子报表
  6. azure机器学习_Azure机器学习中的预测
  7. 缓存 负载均衡_使用“针对临时工作负载优化”选项来保存计划缓存存储
  8. mysql 约束条件 外键 forigen key 介绍
  9. web项目使用配置web.xml实现重定向
  10. 《Java高级程序设计》第一周作业