详解.NET中六个你必须知道的重要概念
创始人
2024-06-29 20:20:39
0次

【51CTO独家特稿】我也制作了很多视频教程,包括设计模式,WCF,WWF,WPF,LINQ,Silverlight,UML,Sharepoint,Azure,VSTS等,可去http://tinyurl.com/mra3hx观看。

好复杂的东西啊

图 1 Oh,My Lady gaga,这些东西好复杂哦

当你声明一个变量时内存中都发生了什么?

当你在一个.Net应用程序中声明一个变量时,首先要分配一些内存快到RAM,它包括三样东西,第一个是变量名,第二个是变量的数据类型,最后一个是变量的值。

这只是一个很简单的解释,根据变量的数据类型不同,有两种内存分配类型:堆栈内存和堆内存。

 

声明变量后的内存结构

图 2 声明变量后的内存结构

堆栈(stack)和堆(heap)

为了帮助理解堆栈和堆,让我们了解下面的代码内部究竟发生了什么。

  1. public void Method1()  
  2. {  
  3. // Line 1  
  4. int i=4;  
  5. // Line 2  
  6. int y=2;  
  7. //Line 3  
  8. class1 cls1 = new class1();  
  9. } 

这个方法内部只有三行代码,下面我就逐行解释内部发生了什么事情。

第一行:执行该行时,编译器分配一小块叫做堆栈的内存,堆栈负责保持跟踪应用程序运行需要的内存。

第二行:现在执行移动到下一步,正如堆栈的名称所暗示的那样,这个内存分配时叠放在前一个内存分配顶部的,你可以将堆栈理解为一系列隔间或盒子的逐层堆积。

内存分配和解除分配使用LIFO(Last in first out,后进先出)逻辑,换句话说就是内存是在内存的末尾(如堆栈的顶部)分配和解除分配的。

第三行:在第三行我们创建了一个对象,执行该行时,它在堆栈上创建一个指针,真实的对象是存储一个不同类型的内存分配(叫做堆)中,堆不会跟踪运行的内存,它只是对象的堆积,堆用于动态内存分配。

退出方法(有趣):执行完最后一行代码后就该退出这个方法了,当它传递结束控制时,它就会清除分配到堆栈上的所有内存变量,换句话说就是所有与int数据类型关联的变量按照LIFO方式从堆栈中解除分配。

但不会解除堆内存分配,这部分内存要通过GARBAGE COLLECTOR(垃圾回收器)解除分配。

 

三行代码对应的内存内部操作

图 3 三行代码对应的内存内部操作

很多人现在可能要问为什么要设置两种内存分配形式呢?难道就不能用一种内存分配形式完成内存分配吗?

如果你仔细观察上图,你就会知道int变量是分配在堆栈上的,因为编译器已经知道它们可以存储多少数据(-2,147,483,648到2,147,483,647),涉及到对象时,编译器不知道需要多少内部空间,因此在堆上分配相同大小的空间。

换句话说就是,如果不知道数据大小或是动态变化的,就需要分配到堆上,如果数据大小是确定的,就分配到堆栈上。

 

不知道变量大小时分配到堆上

 

图 4 知道变量大小时分配到堆栈上,不知道变量大小时分配到堆上

值类型和引用类型

值类型指的是在相同的位置同时容纳数据和内存的类型,而引用类型是借助一个指针指向内存位置。下面是一个简单的命名为i的整数数据类型,其值是由另一个命名为j的整数数据类型赋予的,这两个内存值都是基于堆栈分配的。

当我们将一个int值赋给另一个int值时,它创建一个完全不同的拷贝,换句话说就是,你修改其中一个值不会引起另一个值也发生变化,这种数据类型就叫做值类型。

 

 

值类型

图 5 值类型:一个值的变化不会引起另一个值变化

当我们将一个对象赋值给另一个对象时,它们指向相同的内存位置,如下图所示,当我们将obj赋值给obj1时,它们指向的内存位置是一样的。换句话说就是,如果我们修改了其中一个对象,另一个对象也会受到影响,这种类型就叫做引用类型。

 

 

引用类型

图 6 引用类型:一个对象的变化会引起另一个对象的变化

哪一个数据类型是值类型和引用类型呢?

在.Net中,根据数据类型不同,变量可能是基于堆栈分配的,也可能是基于堆分配的,String和Objects是引用类型,其它.Net数据类型是基于堆栈分配的,下图更详细地进行了解释。

 

引用类型和值类型对应

图 7 引用类型和值类型对应.Net中的数据类型

#p#

装箱(boxing)和拆箱(unboxing)

说了这么多,在实际编程时怎么使用它们呢?最大的问题是要弄清楚数据从堆栈移到堆的性能损失,反之亦然。

如下图所示,当我们将一个值类型移到引用类型时,数据也从堆栈移到堆中,当我们将引用类型移到值类型时,数据就从堆移到堆栈中。数据从堆栈移到堆,或是从堆移到堆栈,都会产生较大的性能损失。数据从值类型移到引用类型的过程叫做装箱,从引用类型移到值类型叫做拆箱。

 

 

 装箱和拆箱过程示意

图 8 装箱和拆箱过程示意

如果你编译上面的代码,在相同的ILDASM中,你会看到在IL中的代码是如何装箱和拆箱的,如下图所示。

 

装箱和拆箱

图 9 装箱和拆箱

装箱和拆箱的性能影响

为了查看性能的影响,我们将下面两个函数运行了1000次,如下图所示,左边的函数有装箱拆箱操作,右边的函数没有,我们使用了一个秒表对象监控所花的时间。

 

有装箱拆箱和无装箱拆箱执行时间对比

图 10 有装箱拆箱和无装箱拆箱执行时间对比

从上图我们看到,有装修拆箱需要花3542毫秒,无装修拆箱只需2477毫秒,因此对性能的影响还是蛮大的。

现在你对这两个重要的.Net概念是否都理解了呢?

原文名:6 important .NET concepts: - Stack, heap, Value types, reference types, boxing and Unboxing.

【编辑推荐】

  1. Visual Studio 2010及.Net 4新功能一览
  2. 升级Visual Studio 2010和.Net 4注意要点
  3. 观点:微软.NET各子技术领域的应用前景
  4. 三方面诠释.NET 4.0的新特性
  5. Java和.NET继续争斗的四大相关问题

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
如何更省钱? 近期特价热门硒鼓... 如今激光打印设备已经成为商务或企业的绝对主力办公设备,但采购者往往忽视了激光打印设备所用的耗材,相对...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...