在C#中,值类型和引用类型是相当重要的两个概念,必须在设计类型的时候就决定类型实例的行为。如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常。很多人就是因为没有弄清楚这两个概念从而在编程过程中遇到了很多问题,在这里博主浅谈对值类型和引用类型的认识。

首先从概念上看,值类型直接存储其值,而引用类型存储对其值的引用。从而这两种类型存储在内存的不同地方。

其次从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。

栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。因此,值类型总是在内存中占用一个预定义的字节数。而引用类型的变量则在栈中分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,即存放此变量实际值的地方。

也就是说值类型相当于现金,要用就直接用,而引类型相当于存折,要用得先去银行取。

但值类型在栈上分配内存,而引用类型在托管堆上分配内存,只是一种笼统的说法。下面对其进行详细描述。

(1)对于值类型的实例,如果作为方法中的局部变量,则被创建在线程栈上;如果该实例作为类型的成员,则作为类型成员的一部分,连同其他类型字段存放在托管堆上。

每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。例如:

int i = new int(); 

等价于:

Int32 i = new Int32(); 

等价于:

int i = ; 

等价于:

Int32 i = ; 

使用new运算符时,将调用特定类型的默认构造函数并对变量赋以默认值。在上例中,默认构造函数将值0赋给了i。

说明:C#的所有值类型均隐式派生自System.ValueType,而System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。

(2)引用类型的实例创建在托管堆上。

下面以一段代码来详细讲解一下值类型与引用类型的区别

    namespace Test
{
class Program
{
static void Main(string[] args)
{
//调用ReferenceAndValue类中的Demonstration方法
ReferenceAndValue.Demonstration();
Console.ReadLine();
}
}
public class stamp //定义一个类
{
public string Name { get; set; } //定义引用类型
public int Age { get; set; } //定义值类型
}
public static class ReferenceAndValue //定义一个静态类
{
public static void Demonstration() //定义一个静态方法
{
stamp Stamp_1 = new stamp { Name = "Premiere", Age = }; //实例化
stamp Stamp_2 = new stamp { Name = "Again", Age = }; //实例化
int age = Stamp_1.Age; //获取值类型Age的值
Stamp_1.Age = ; //修改值类型的值
stamp guru = Stamp_2; //获取Stamp_2中的值
Stamp_2.Name = "Again Amend"; //修改引用的Name值
Console.WriteLine("Stamp_1's age:{0}", Stamp_1.Age); //显示Stamp_1中的Age值
Console.WriteLine("age's value:{0}", age); //显示age值
Console.WriteLine("Stamp_2's name:{0}", Stamp_2.Name); //显示Stamp_2中的Name值
Console.WriteLine("guru's name:{0}", guru.Name); //显示guru中的Name值
}
}
}

通过运行上面一段程序之后我们可以看出,当改变了Stamp_1.Age的值时,age并没有跟着变,但在改变了anders.Name的值后,guru.Name却跟着变了,这就是值类型和引用类型的区别。在声明age值类型变量时,将 Stamp_1.Age的值赋给它,这时,编译器在栈上分配了一块空间,然后把Stamp_1.Age的值填进去,二者没有任何关联,就像在计算机中复制文件一样,只是把Stamp_1.Age的值拷贝给age了。而引用类型则不同,在声明guru时把Stamp_2赋给它,前面说过,引用类型包含的只是堆上数据区域地址的引用,其实就是把Stamp_2的引用也赋给guru,因此它们指向了同一块内存区域。既然是指向同一块区域,不管修改谁,另一个的值都会跟着改变,就像信用卡跟亲情卡一样,用亲情卡取了钱,与之关联的信用卡账上也会跟着发生变化。

作者:耑新新,发布于  博客园

转载请注明出处,欢迎邮件交流:zhuanxinxin@aliyun.com

浅谈C#中的值类型和引用类型的更多相关文章

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

    在C#中,值类型和引用类型是相当重要的两个概念,必须在设计类型的时候就决定类型实例的行为.如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常.很多人就是因为没有弄清楚这两个 ...

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

    原文 C# 中的值类型和引用类型 值类型(value type):int,long,float,double,decimal,char,bool 和 struct 统称为值类型.值类型变量声明后,不管 ...

  3. C++ : 从栈和堆来理解C#中的值类型和引用类型

    C++中并没有值类型和引用类型之说,标准变量或者自定义对象的存取默认是没有区别的.但如果深入地来看,就要了解C++中,管理数据的两大内存区域:栈和堆. 栈(stack)是类似于一个先进后出的抽屉.它的 ...

  4. C#中的值类型和引用类型,深拷贝,浅拷贝

    from https://www.jianshu.com/p/2d27b06e253f 一.C#中的值类型和引用类型 概念 值类型直接存储其值. 引用类型存储对值的引用. 说起来有些拗口,其本质是Va ...

  5. .NET中的值类型与引用类型

    .NET中的值类型与引用类型 这是一个常见面试题,值类型(Value Type)和引用类型(Reference Type)有什么区别?他们性能方面有什么区别? TL;DR(先看结论) 值类型 引用类型 ...

  6. Windows Phone 开发起步之旅之二 C#中的值类型和引用类型

    今天和大家分享下本人也说不清楚的一个C#基础知识,我说不清楚,所以我才想把它总结一下,以帮助我自己理解这个知识上的盲点,顺便也和同我一样不是很清楚的人一起学习下.  一说起来C#中的数据类型有哪些,大 ...

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

    区别值类型和引用类型的重要一点就是值类型赋值的时候是给出一块内存空间,空间里放下要赋给值类型的值.而引用类型是开辟一块内存空间,空间里放下的是要赋给引用类型值的指向地址. 就像一个是复制了银行卡里的现 ...

  8. js中的值类型和引用类型的区别

    1.JavaScript中的变量类型有哪些? (1)值类型(基本类型):字符串(String).数值(Number).布尔值(Boolean).Undefined.Null  (这5种基本数据类型是按 ...

  9. C#中的值类型、引用类型,代码告诉你他是什么类型。

    C#代码告诉你这是什么类型. using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

随机推荐

  1. Linux运维七:网络基础

    1:网线 2:交换机,路由器 交换机(Switch)意为“开关”是一种用于电(光)信号转发的网络设备.它可以为接入交换机的任意两个网络节点提供独享的电信号通路.最常见的交换机是以太网交换机.其他常见的 ...

  2. Java并发编程原理与实战三十:CountDownLatch与CyclicBarrier 区别

    相信每个想深入了解多线程开发的Java开发者都会遇到CountDownLatch和CyclicBarrier,大家也在网上看到各种介绍原理,代码的,以及他们区别(应付面试)的,但是很少能讲清楚:他们到 ...

  3. 【js学习笔记】去除省、市、区、特别行政区、自治区

    不是很懂js,以前去除这些省.市.区的时候都是用的分支判断indexOf,如果!=-1则replace一次,今天看同事的代码,发现还有更简单的办法... var areaName = str.repl ...

  4. spring-boot Test for Controller

    spring-boot  controller 测试示例: 单元测试类 package com.zzhi; import com.fasterxml.jackson.databind.ObjectMa ...

  5. RulersGuides.js – 网站中实现 Photoshop 标尺效果

    RulersGuides.js 是一个 JavaScript 库,在网页上添加类似 Photoshop 中的标尺和辅助网格线.要创建创建网格线线,请单击垂直或水平的标尺,然后推动就可以.还可以使用相应 ...

  6. HDU 2097 Sky数 进制转换

    解题报告:这题就用一个进制转换的函数就可以了,不需要转换成相应的进制数,只要求出相应进制的数的各位的和就可以了. #include<cstdio> #include<string&g ...

  7. Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))

    题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...

  8. 30、hashCode方法

    HashCode方法的作用 在HashSet中的元素是不能重复的,jvm可以通过equals方法来判断两个对象是否相同,假设自定义一个Person类里面有10个成员变量,每调用一次equals方法需要 ...

  9. node.js 基础篇

    日志输出方式 node test.js 2>error.log 1>info.log 如果需要日志文件追加 node test.js 2>>error.log 1>> ...

  10. 状压dp+floyed(C - Hie with the Pie POJ - 3311 )

    题目链接:https://cn.vjudge.net/contest/276236#problem/C 题目大意: 给你一个有n+1(1<=n<=10)个点的有向完全图,用矩阵的形式给出任 ...