C#基础入门之值类型和引用类型的区别详析

目录
  • 一、值类型和引用类型的区别
    • 1、赋值时的区别
    • 2、内存分配的区别
    • 3、来自继承结构的区别
  • 二、总结

一、值类型和引用类型的区别

.NET的类型可以分为两类:值类型和引用类型。这两种类型各有特点,即使它们都继承自System.Object,并且有装箱和拆箱等操作确保两种类型可以方便地交互,但是理解值类型和引用类型将有助于程序员编写出高效的代码,相反的,在不理解值类型和引用类型的情况下,程序员很容易编写出可以正确执行但性能较差的代码。

所有.NET的类型都可以分为两类:值类型和引用类型。最简单也最明确的一个区分标准是:所有的值类型都继承自System.ValueType(System.ValueType继承自System.Object),也就是说,所有继承自System.ValueType的类型都是值类型,而其他类型都是引用类型。常用的值类型包括结构、枚举、整数型、浮点型、布尔型等,而在C#中所有以class关键字定义的类型都是引用类型。

1、赋值时的区别

引用类型和值类型最显著的一个区别在于变量的赋值问题。值类型的变量将直接获得一个真实的数据副本,而对引用类型的赋值仅仅是把对象的引用赋给变量,这样就可能导致多个变量引用到一个实际对象实例上。

来看下面一个简单的示例:首先为了测试建立一个简单的引用类型和一个简单的值类型。然后在Main方法中,测试对值类型和引用类型对象进行赋值的不同结果,代码如下:

using System;

namespace ConsoleApp1
{
    /// <summary>
    /// 一个简单的引用类型
    /// </summary>
    public class Ref
    {
        public int iValue { get; set; }

        public Ref(int i)
        {
            iValue = i;
        }

        public override string ToString()
        {
            return $"iValue的值为:{iValue.ToString()}";
        }
    }

    /// <summary>
    /// 一个简单的值类型
    /// </summary>
    public struct Val
    {
        public int Value { get; set; }

        public Val(int i)
        {
            Value = i;
        }

        public override string ToString()
        {
            return $"Value的值为:{Value.ToString()}";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // 测试引用类型的赋值
            Ref ref1 = new Ref(1);
            Ref ref2 = ref1;
            // 赋值
            ref2.iValue = 2;

            // 测试值类型的赋值
            Val val1 = new Val(1);
            Val val2 = val1;
            val2.Value = 2;
            //输出
            Console.WriteLine($"ref1:{ref1}");
            Console.WriteLine($"ref2:{ref2}");
            Console.WriteLine($"val1:{val1}");
            Console.WriteLine($"val2:{val2}");
            Console.ReadKey();
        }
    }
}

简单分析上面的代码,程序定义了一个引用类型Ref和一个值类型Val,两者的内容几乎完全相同。在Main方法中,分别测试了引用类型和值类型的赋值。当代码把一个引用类型变量赋值给另一个引用变量:Ref ref2 = ref1时,实际上是把ref1的对象引用赋给了ref2,这样,两个引用变量实际指向了同一个对象。如图所示:

而值类型的赋值则不同,val1和val2都保留了属于自己的数据副本,所以当val2改变时,val1不受到影响。如图所示:

上面代码的输出结果:

2、内存分配的区别

除了赋值的区别,引用类型和值类型在内存的分配位置上也有区别。引用类型的对象将会在堆上分配内存,而值类型的对象则会在堆栈上分配内存。堆栈的空间相对有限,但运行效率却比高的多。

3、来自继承结构的区别

最后,由于所有的值类型都有一个共同的基类:System.ValueType,所以值类型拥有一些引用类型不具有的共同性质,较重要的一点是值类型的比较方法:Equals方法的实现有了改变。所有的值类型都实现了内容的比较,而引用类型在没有重写Equals方法的情况下,仍然采用引用比较。还是以上面的代码为了,看下面的代码:

using System;

namespace ConsoleApp1
{
    /// <summary>
    /// 一个简单的引用类型
    /// </summary>
    public class Ref
    {
        public int iValue { get; set; }

        public Ref(int i)
        {
            iValue = i;
        }

        public override string ToString()
        {
            return $"iValue的值为:{iValue.ToString()}";
        }
    }

    /// <summary>
    /// 一个简单的值类型
    /// </summary>
    public struct Val
    {
        public int Value { get; set; }

        public Val(int i)
        {
            Value = i;
        }

        public override string ToString()
        {
            return $"Value的值为:{Value.ToString()}";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //// 测试引用类型的赋值
            //Ref ref1 = new Ref(1);
            //Ref ref2 = ref1;
            //// 赋值
            //ref2.iValue = 2;

            //// 测试值类型的赋值
            //Val val1 = new Val(1);
            //Val val2 = val1;
            //val2.Value = 2;

            //输出
            //Console.WriteLine($"ref1:{ref1}");
            //Console.WriteLine($"ref2:{ref2}");
            //Console.WriteLine($"val1:{val1}");
            //Console.WriteLine($"val2:{val2}");

            // 测试引用类型的赋值
            Ref ref1 = new Ref(1);
            Ref ref2 = new Ref(1);

            // 测试值类型的赋值
            Val val1 = new Val(1);
            Val val2 = new Val(1);

            Console.WriteLine(ref1.Equals(ref2));
            Console.WriteLine(val1.Equals(val2));
            Console.ReadKey();
        }
    }
}

程序输出结果:

在Main方法中,分别定义了一对内容完全相同的值类型对象和引用类型对象,调用Equals方法来比较,发现值类型对象比较返回true,而引用类型对象比较返回false。

二、总结

所有继承自System.ValueType的类型都是值类型,而其他类型都是引用类型。值类型的赋值会产生一个新的数据副本,所以每个值类型都拥有一个数据副本。而引用类型的赋值则是赋值引用。值类型的对象分配在堆栈上,而引用类型的对象分配在堆上。当比较两个值类型时,进行的是内容比较。而比较两个引用类型时,进行的是引用比较。

上面列举的仅仅是值类型和引用类型的一些主要区别,通过这些本质区别,可以产生更多的细节区别,有兴趣的话可以自行研究。

到此这篇关于C#基础入门之值类型和引用类型区别的文章就介绍到这了,更多相关C#值类型和引用类型区别内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C# 语言入门基础介绍

    目录 一..NET 体系结构 二.Hello world 三.类型和变量 四.程序结构 前言: C#(读作"See Sharp")是一种新式编程语言,不仅面向对象,还类型安全. 开发人员利用 C# 能够生成在 .NET 中运行的多种安全可靠的应用程序. C# 源于 C 语言系列,C.C++.Java 和 JavaScript 程序员很快就可以上手使用. 本教程概述了 C# 8 及更高版本中该语言的主要组件. C# 是面向对象的.面向组件的编程语言. C# 提供了语言构造来直接支持这些概

  • C# 异步多线程入门基础

    目录 进程.线程 1. 进程 2. 线程 分时.分片 同步.异步 异步.多线程 异步多线程效率 多线程无序性 扩展 异步多线程版本 下一篇:C# 异步多线程入门到精通之Thread篇 进程.线程 1. 进程 首先了解,什么是线程? 即一个应用程序运行时,占用资源的综合是一个进程.Windows 任务管理器里面可以看到,里面一个个都是在运行的进程. 2. 线程 线程是执行流的最小单位.线程其实是看不到的,其实也可以,例如 Windows 任务管理器:正在运行 272 个进程,272 个进程运行了

  • 轻松学习C#的基础入门

    C#是一种简单的,安全的,稳定的,由C和C++衍生出来的面向对象的编程语言,它在继承C和C++强大功能的同时,去掉了它们的一些复杂性,综合了Visual Studio简单的可视化操作和C++高效的运行效率,以其强大的操作能力,独特的语法风格,创新的语言特性,便捷的面向组件编程的支持,使其成为.NET开发的首选语言,并成为ECMA和ISO的标准规范.        C#和Java有着惊人的相似,主要包括诸如单一继承,接口,与Java几乎同样的语法和编译成中间代码在运行的过程.但是C#和Java有着

  • C# 多线程学习之基础入门

    目录 同步方式 异步多线程方式 异步多线程优化 异步回调 异步信号量 异步多线程返回值 异步多线程返回值回调 线程(英语:thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.进程是资源分配的基本单位.所有与该进程有关的资源,都被记录在进程控制块PCB中.以表示该进程拥有这些资源或正在使用它们.本文以一些简单的小例子,简述如何将程序由同步方式,一步一步演变成

  • C#基础入门之值类型和引用类型的区别详析

    目录 一.值类型和引用类型的区别 1.赋值时的区别 2.内存分配的区别 3.来自继承结构的区别 二.总结 一.值类型和引用类型的区别 .NET的类型可以分为两类:值类型和引用类型.这两种类型各有特点,即使它们都继承自System.Object,并且有装箱和拆箱等操作确保两种类型可以方便地交互,但是理解值类型和引用类型将有助于程序员编写出高效的代码,相反的,在不理解值类型和引用类型的情况下,程序员很容易编写出可以正确执行但性能较差的代码. 所有.NET的类型都可以分为两类:值类型和引用类型.最简单

  • js中值类型和引用类型的区别介绍

    1.JavaScript中的变量类型有哪些? (1)值类型(基本类型):字符串(string).数值(number).布尔值(boolean).undefined.null  .symbol (2)引用类型:对象(Object).数组(Array).函数(Function) 2.值类型和引用类型的区别 (1)值类型: 1.占用空间固定,保存在栈中(当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了.因

  • C#中值类型和引用类型的区别深度分析

    本文通俗易懂的分析了C#中值类型和引用类型的区别.分享给大家供大家参考.具体分析如下: 似乎"值类型和引用类型的区别"是今年面试的流行趋势,我已然是连续三次(目前总共也就三次)面试第一个问题就遇到这个了,这是多大的概率啊,100%,哈哈,我该买彩票去! 言归正传,咱还是先来探讨探讨这二者之间有什么区别吧.记得有一次电话面试中,我直接跟面试官说:"值类型是现金,引用类型是存折",后来想想当时说这话虽是有点儿冲动地脱口而出,但也没什么不妥.我这人不善于背理论的教条,喜欢

  • JavaScript中值类型和引用类型的区别

    JavaScript的数据类型分为两类:原始类型和对象类型.其中,原始类型包括:数字.字符串和布尔值.此外,JavaScript中还有两个特殊的原始值:null和undefined,它们既不是数字也不是字符串,更不是布尔值.它们通常分别代表了各自特殊类型的唯一成员.JavaScript中除了数字.字符串.布尔值.null和undefined之外的就是对象了. JavaScript中值类型和引用类型的区别 JavaScript中的值类型的值是不可变的: 任何方法都无法改变值类型的值.数字.布尔值.

  • JAVA中值类型和引用类型的区别

     1. Java中值类型和引用类型的不同? [定义] 引用类型表示你操作的数据是同一个,也就是说当你传一个参数给另一个方法时,你在另一个方法中改变这个变量的值, 那么调用这个方法是传入的变量的值也将改变.值类型表示复制一个当前变量传给方法, 当你在这个方法中改变这个变量的值时,最初生命的变量的值不会变.通俗说法: 值类型就是现金,要用直接用:引用类型是存折,要用还得先去银行取现.----(摘自网上) [值类型] 也就是基本数据类型 基本数据类型常被称为四类八种 四类:  1,整型 2,浮点型 3

  • C#中值类型和引用类型的区别

    一.值类型和引用类型的区别 .NET的类型可以分为两类:值类型和引用类型.这两种类型各有特点,即使它们都继承自System.Object,并且有装箱和拆箱等操作确保两种类型可以方便地交互,但是理解值类型和引用类型将有助于程序员编写出高效的代码,相反的,在不理解值类型和引用类型的情况下,程序员很容易编写出可以正确执行但性能较差的代码. 所有.NET的类型都可以分为两类:值类型和引用类型.最简单也最明确的一个区分标准是:所有的值类型都继承自System.ValueType(System.ValueT

  • c#基础系列之值类型和引用类型的深入理解

    前言 不知不觉已经踏入坑已10余年之多,对于c#多多少少有一点自己的认识,写出来渴求同类抨击,对自己也算是个十年之痒的一个总结. C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存储位置的不同会有不同的影响. 下面话不多说了,来一起看看详细的介绍吧 基本概念 CLR支持两种类型:值类型和引用类型. 面试过很多5年左右的同学,有很多连值类型和引用类型的基

  • 值类型和引用类型的区别深入理解

    区别: 1.值类型通常被分配在栈上,它的变量直接包含变量的实例,使用效率比较高. 2.引用类型分配在托管堆上,引用类型的变量通常包含一个指向实例的指针,变量通过该指针来引用实例.3.值类型继承自ValueType(注意:而System.ValueType又继承自System.Object):而引用类型继承自System.Object. 4.值类型变量包含其实例数据,每个变量保存了其本身的数据拷贝(副本),因此在默认情况下,值类型的参数传递不会影响参数本身:而引用类型变量保存了其数据的引用地址,因

  • c#中值类型和引用类型的基础教程

    前言 值类型和引用类型,是c#比较基础,也必须掌握的知识点,但是也不是那么轻易就能掌握,今天跟着老胡一起来看看吧. 典型类型 首先我们看看这两种不同的类型有哪些比较典型的代表. 典型值类型 int, long, float, double等原始类型中表示数字的类型都是值类型,表示时间的datatime也是值类型,除此之外我们还可以通过关键字struct自定义值类型. 典型引用类型 原始类型中,array, list, dictionary, queue, stack和string都是引用类型,除

  • Java中值类型和引用类型的比较与问题解决

    一.问题描述 前几天因为一个需求出现了Bug.说高级点也挺高级,说白点也很简单.其实也就是一个很简单的Java基础入门时候的值类型和引用类型的区别.只是开发的时候由于自己的问题,导致小问题的出现.还好突然想起来以前看过一篇对于该问题讲解的博客,才能快速定位问题的位置.防止下次再犯,顺便也就把这个当做笔记记录下来,放入自己的Bug集中. 二.值类型和引用类型的比较 这个大家应该都是没问题的,很简单.值类型比较是比较值,引用类型是比较地址.对于正常的操作来说,比较值类型我们可以直接使用 == ,引用

随机推荐