探索C#中的值类型和引用类型

  记得大三上学期上C#课程的时候,老师第一堂课就重点给我们讲了一下C#中的数据类型。我们都知道,C#是一门强类型的高级编程语言,了解它的数据类型是非常有必要的。老师当时给我们列举了很多数据类型,然后问我们哪些是值类型,那些是引用类型。说实话,当时对于这个问题还真是回答不上来,或许可以说是自己没有多少底气回答。虽然大一学C++的时候接触过值类型和引用类型,但是因为没有深究,或者根本没有真正了解他们的区别,以至于在自己写代码时无形当中用到了却还是不了解它们之间的具体区别。

  现在大四了,也到了快紧张面试的时候,自己也会去找一些关于.net方面的面试题看。通过一些途径了解到,有很多企业在面试时把基础放在重要的位置,像今天所说的值类型和引用类型的问题在ASPNet等Web方向的面试中就可能经常出现,所以我觉得很有必要好好弄清以下这两个概念以及它们之间的区别。

  以前,在我印象中,可能就是把值类型理解为我们常用的那些基本数据类型(整形、浮点型、字符型、字符串、结构体等等),把引用类型理解为类、指针等,其实这样的理解是不全面的甚至可以说是错误的。那么究竟什么是值类型,什么又是引用类型呢?

  整体来说,C#的值类型有:

  整型:int;长整型:long;浮点型:float;字符型:char;布尔型:bool;枚举:enum;结构体:struct

  C#的引用类型有:

  类:class;接口:interface;数组:int[],string[];委托;装箱值类型

  为了方便大家记忆和理解,我从网上找来一张图展示值类型和引用类型,清晰易懂

  

  我们可以看到,C#中的值类型包括7种数据类型,这里要特别注意,并不是所有的基本数据类型都是值类型,像string就是引用类型,我们可以把它看成一个类。还有一点,结构体虽然与类有点相似,但它是值类型,类是引用类型,这是他们主要的区别之一。然后引用类型中类和接口大家都能接受,但是不能忘了数组也是引用类型,委托和装箱值类型因为目前我还不是很了解,所以只能强记了。但是说到委托,那必须值得一提,这是C#中一个非常重要的知识点,函数名作为参数传递调用是多么的神奇,想想就有点小激动。但现在写代码我几乎没怎么用委托,由此看来我必须要好好了解一下委托,找机会针对委托写一片关于“探索C#中的委托”的博客。

  了解了值类型和引用类型之后,那它们的区别是什么呢?

  从概念上看,值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的地址,即对象的引用。

  从内存空间上看,值类型的数据存储在内存的栈中,作用域结束时,所占空间自行释放,效率高,无需进行地址转换;而引用类型的数据存储在内存的托管堆中,内存单元中只存放堆中对象的地址,由GC来控制其回收,需要进行地址转换,效率降低,这也正是C#需要定义两种数据类型的原因之一。

  值类型和引用类型在函数参数传值时是有区别的,首先来看一段经过自己运行并成功的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Person
    {
        public int Blood = 10;
    }

    class Program
    {
        public static void Add(int x)
        {
            x += 10;
            Console.WriteLine("值类型当参数被传递并修改之后:" + x);
        }

        public static void Add(Person person)
        {
            person.Blood += 10;
            Console.WriteLine("引用类型当参数被传递并修改之后:" + person.Blood);
        }

        static void Main(string[] args)
        {
            //值类型变量
            int i = 10;

            Console.WriteLine("i的原值:" + i);
            Add(i);
            Console.WriteLine("但是i的值并没有因为函数的修改而修改:" + i + ‘\n‘);

            //引用类型变量
            Person person = new Person();

            Console.WriteLine("Blood的原值:" + person.Blood);
            Add(person);
            Console.WriteLine("但是Blood的值因为函数的修改而修改:" + person.Blood);

            //值类型和引用类型的区别,就在于当函数参数传递的时候.
            //值类型是把自己的值复制一份传递给别的函数操作.无论复制的值怎么被改变.其自身的值是不会改变的
            //而引用类型是把自己的内存地址传递给别的函数操作.操作的就是引用类型值的本身.所以值被函数改变了.
            //这就是传值和传址的区别

            Console.ReadLine();
        }
    }
}

从以下结果可以看到两种类型函数传参时的区别:(以上代码中的注释解释了原因)

  那么文章就先写到这里了,初次写博客,或许存在很多问题,如有问题欢迎大家指出,我将认真改正。写这篇博客是为了让自己在写的过程中理解一些知识及备忘,研究的并不是那么深入,或许不够完善,还望大家见谅。

时间: 2024-08-27 02:44:39

探索C#中的值类型和引用类型的相关文章

JavaScript中的值类型和引用类型

先抛出一个题目,阿里的笔试面试题(很基础,但确实是阿里的笔试题) var a = {"x": 1}; var b = a; a.x = 2; a = {"x": 3}; console.log(b.x); 大家觉得最后在控制台输出的结果是多少? 如果你答案是2,那你就没必要接下去看了.如果不是.那你就接着看下去来解决你的疑惑吧! JavaScript中的值类型和引用类型 在javascript里面有两种变量类型,一种是值类型,一种是引用类型. 值类型:数值.布尔型.

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

原文 C# 中的值类型和引用类型 值类型(value type):int,long,float,double,decimal,char,bool 和 struct 统称为值类型.值类型变量声明后,不管是否已经赋值,编译器为其分配内存. 引用类型(reference type):string 和 class统称为引用类型.当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间.当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的

C#中对值类型和引用类型的一点认识

区别值类型和引用类型的重要一点就是值类型赋值的时候是给出一块内存空间,空间里放下要赋给值类型的值.而引用类型是开辟一块内存空间,空间里放下的是要赋给引用类型值的指向地址. 就像一个是复制了银行卡里的现金,你花了你复制的现金,和该银行卡是没有关系的.而引用类型是复制了一个银行卡,此卡为银行卡的副卡,因为他们的指向地址是一样的,所以当你使用副卡 的时候,主卡里的钱也会随之变动. 下面给出一段代码. using System; using System.Collections.Generic; usi

浅谈C#中的值类型和引用类型

在C#中,值类型和引用类型是相当重要的两个概念,必须在设计类型的时候就决定类型实例的行为.如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常.很多人就是因为没有弄清楚这两个概念从而在编程过程中遇到了很多问题,在这里博主浅谈对值类型和引用类型的认识. 首先从概念上看,值类型直接存储其值,而引用类型存储对其值的引用.从而这两种类型存储在内存的不同地方. 其次从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元. 栈在编译的时候就分配好内存空间,在代码中有栈的

【.Net】浅谈C#中的值类型和引用类型

在C#中,值类型和引用类型是相当重要的两个概念,必须在设计类型的时候就决定类型实例的行为.如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常.很多人就是因为没有弄清楚这两个概念从而在编程过程中遇到了很多问题,在这里博主浅谈对值类型和引用类型的认识. 首先从概念上看,值类型直接存储其值,而引用类型存储对其值的引用.从而这两种类型存储在内存的不同地方. 其次从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元. 栈在编译的时候就分配好内存空间,在代码中有栈的

C#中的值类型与引用类型

这些天学习C#,看到里面的值类型与引用类型,例如结构是值类型,类是引用类型,然后立马想到了C++中的类,那么C++中的类是什么类型呢,哈哈,忽然间有点迷惑,上网搜了搜还真有很多小伙伴们已经晕进去了,今天就总结一下C#与C++中值类型与引用类型的区别. 其实C#中值类型与引用类型的根本区别就是变量包含的数据在哪个内存区间上,值类型在堆栈中直接包含,引用类型在堆中间接引用,例如,C#中实例化类必需要下面的语法: Class name = newclass(); 很容易看出来,类是在堆中分配的空间,然

C#中的值类型和引用类型以及堆栈

引用类型如:string,Object,class等总是在从托管堆上分配的,C#中new操作符返回对象的内存地址--也就是指向对象数据的内存地址. 以下是值类型与引用类型的表: 我们来看下面一段代码: 首先在类中声明一个class类,和一个struct结构,如图: 并使用在程序入口调用它们,如图: 现在我们来看一看,它们在内存当中是如何存储的? 从这张图可以看出,class(类)实例化出来的对象,指向了内存堆中分配的空间 struct(结构) 实例化出来的对象,是在内存栈中分配 接下来,我们再来

Go语言中的值类型和引用类型

一.值类型和引用类型值类型:int.float.bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中.当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝.可以通过 &i 获取变量 i 的内存地址.  值拷贝 引用类型:特指slice.map.channel这三种预定义类型.引用类型拥有更复杂的存储结构:(1)分配内存 (2)初始化一系列属性等一个引用类型的变量r1存储的是r1的值所在的内

C#中关于值类型和引用类型的个人理解

值类型,除了最终继承自Object,还继承自ValueType 值类型继承ValueType,ValueType继承Object.(c#中所有的类型都最终继承自Object) 创建引用类型时,runtime会为其分配两个空间,一块空间分配在堆上,存储引用类型本身的数据,另一个块空间分配在栈上,存储对堆上数据的引用(实际上存储的堆上的内存地址,也就是指针). 创建值类型时, runtime会为其分配一个空间,这个空间分配在变量创建的地方,如: 如果值类型是在方法内部创建,则跟随方法入栈,分配到栈上