.NET中栈和堆的比较
- 格式:doc
- 大小:404.00 KB
- 文档页数:37
.NET开发人员试题(综合)每题5分1、用.net做B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为什么要这样分层?2、软件开发过程一般有几个阶段?每个阶段的作用?3、请列举一些您用到过的设计模式以及在什么情况下使用该模式?4、您对编程的兴趣如何?工作中遇到不懂的问题是怎样去解决的?您一般怎样去提高自己的编程水平?5、您离职的原因是什么?.NET开发人员试题(基础)一、填空:每题2分1.面向对象的语言具有继承性、封装性、多态性。
2. 能用foreach遍历访问的对象需要实现 IEnumerable _接口或声明3.委托声明的关键字是delegate ?4.在.Net托管代码中我们不用担心内存漏洞,这是因为有了gc __?5.当类T只声明了私有实例构造函数时,则在T的程序文本外部,不可以(可以or 不可以)从T派生出新的类,不可以(可以or 不可以)直接创建T的任何实例。
二、单选:每题2分6.在对SQL Server 数据库操作时应选用(A)。
a)SQL Server .NET Framework 数据提供程序;b)OLE DB .NET Framework 数据提供程序;c)ODBC .NET Framework 数据提供程序;d)Oracle .NET Framework数据提供程序;7.以下描述错误的是(A)a)在C++中支持抽象类而在C#中不支持抽象类。
b)C++中可在头文件中声明类的成员而在CPP文件中定义类的成员,在C#中没有头文件并且在同一处声明和定义类的成员。
c)在C#中可使用new 修饰符显式隐藏从基类继承的成员。
d)在C#中要在派生类中重新定义基类的虚函数必须在前面加Override。
8.C#的数据类型有(A)a)值类型和调用类型;b)值类型和引用类型;c)引用类型和关系类型;d)关系类型和调用类型;9.下列描述错误的是(D)a)类不可以多重继承而接口可以;b)抽象类自身可以定义成员而接口不可以;c)抽象类和接口都不能被实例化;d)一个类可以有多个基类和多个基接口;10.在DOM中,装载一个XML文档的方法(D)a)save方法b)load方法c)loadXML方法d)send方法三、不定项选择:每题3分11. 以下叙述正确的是:B CA. 接口中可以有虚方法。
.NET平台常见技术框架整理汇总使⽤.NET平台开发有段时间了,在⽹上资料的基础上做了进⼀步整理,汇集了.NET平台常见的技术框架。
参考资料:1.知识⽹络2.分类清单名称说明地址Windows ServerAppFabric微软⾃家分布式缓存服务框架, 扩展了 Windows Server 为 Web 应⽤程序和中间层服务提供增强的托管、管理和缓存功能Memcahed⾼性能的分布式内存对象缓存系统。
它基于⼀个存储键/值对的hashmap,通过在内存中缓存数据和对象来减少读取数据库的次数,从⽽提⾼动态、数据库驱动⽹站的速度。
Redis使⽤ANSI C语⾔编写、⽀持⽹络、可基于内存亦可持久化的⽇志型、Key-Value数据库,并提供多种语⾔的APINCache基于NGINX的Web服务器构建起来的缓存系统,适⽤于需要快速部署、⼤并发量、⼤存储量的需求2.2.应⽤框架名称说明地址Boilerplate基于领域驱动的开源Web开发框架Orchard国外⼀个MVC开源的博客系统。
DasBlog国外⼀个基于的博客系统国外⼀款免费开源的博客系统。
⼀套⾮常优秀的基于的开源门户⽹站程序。
国内开源的论坛社区系统。
nopCommerce和Aspxcommerce国外⼀套⾼质量的开源B2C⽹站系统。
DTCMS国内两款开源的⽹站管理系统2.3.⽇志记录异常处理名称说明地址Log4Net轻量级的免费开源.NET⽇志记录框架。
Enterprise Library LogApplication Black微软企业库⽇志记录。
Elmah实现最流⾏的应⽤异常⽇志记录框架。
NLog简单灵活的⽇志记录类库,性能⽐Log4Net⾼,使⽤和维护难度低。
Essential Diagnostics为内置System.Diagnostics 命名空间扩展功能,提供更灵活的⽇志功能。
官⽹Logary mono 和 .Net 平台下⾼性能、多⽬标的⽇志、度量、追踪和健康检查库。
.Net笔试题1:说说什么叫字符串不可变?string s="abc";s="123"字符串s不就变了吗?答:String 对象是不可改变的。
每次使用System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。
String是不可变的。
在这段代码中,s原先指向一个String对象,内容是 "abc",然后我们将s指向"123",那么s所指向的那个对象是否发生了改变呢?答案是没有。
这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"123",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
扩展:在需要对字符串执行重复修改的情况下,与创建新的String 对象相关的系统开销可能会非常昂贵。
如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder 类。
例如,当在一个循环中将许多字符串连接在一起时,使用StringBuilder类可以提升性能。
.net笔试题2:BS与CS的联系与区别?答:C/S是Client/Server的缩写。
客户端需要安装专用的客户端软件。
B/S是Brower/Server的缩写,客户机上只要安装一个浏览器。
在这种结构下,用户界面完全通过浏览器实现,一部分事务逻辑在前端实现,但是主要逻辑在服务器端实现。
浏览器通过Web Server 同数据库进行数据交互。
C/S 与B/S 区别:1).硬件环境不同:C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.B/S 一般建立在广域网之上的, 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行。
2).对安全要求不同C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。
update Basic_Role set loginInitialPage='' where loginInitialPage is null1.new有几种用法第一种:new Class();第二种:覆盖方法public new XXXX(){}第三种:new 约束指定泛型类声明中的任何类型参数都必须有公共的无参数构造函数。
2.如何把一个array复制到arrayList里foreach( object o in array )arrayList.Add(o);3.datagrid.datasouse可以连接什么数据源[dataset,datatable,dataview]dataset,datatable,dataview , IList4.概述反射和序列化反射:程序集包含模块,而模块包含类型,类型又包含成员。
反射则提供了封装程序集、模块和类型的对象。
您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。
然后,可以调用类型的方法或访问其字段和属性序列化:序列化是将对象转换为容易传输的格式的过程。
例如,可以序列化一个对象,然后使用HTTP 通过Internet 在客户端和服务器之间传输该对象。
在另一端,反序列化将从该流重新构造对象。
5.概述o/r mapping 的原理利用反射,配置将类于数据库表映射6.类成员有( )种可访问形式可访问形式?不懂。
可访问性:public ,protected ,private,internal7.用sealed修饰的类有什么特点sealed 修饰符用于防止从所修饰的类派生出其它类。
如果一个密封类被指定为其他类的基类,则会发生编译时错误。
密封类不能同时为抽象类。
sealed 修饰符主要用于防止非有意的派生,但是它还能促使某些运行时优化。
具体说来,由于密封类永远不会有任何派生类,所以对密封类的实例的虚拟函数成员的调用可以转换为非虚拟调用来处理。
C#程序性能优化程序中我们每一丝动作都会加大程序运行的负担,当刚开始学习程序的时候常常不会去考虑程序运行的效率,大多数情况是为了实现功能,只要功能达到我想要的那么就算是达成了此项目标。
当大部分功能的编码实现对我们来说都不是大的问题的时候,我们要提升就要考虑怎样把程序写的更加规范更加高效。
怎样写的高效,我们不说整体架构的设计,仅仅分享一下C#自身程序中的一些会影响性能的点。
1.垃圾回收.NET Framework垃圾回收的成本高,每次回收垃圾的时候调用最久未被使用的算法,找出最久未被使用的对象然后把这个对象分配的内存进行回收。
进行这样的算法会非常消耗计算机的运算能力,所以在C#程序编码中避免创建不必要的对象。
1.1避免在循环中创建对象高效的做法是将对象的创建置于循环之外。
但是如果每一次循环需要实例化一个对象加入到对象列表中这个就避免不了在循环内部创建对象,如果把这个对象创建在对象之外那么会导致循环多次加入到列表中的对象是循环最后一次对象的数据了。
1.2在需要的地方才创建对象如果对象只有在某些分支逻辑中才会被使用到,那么把具体创建对象的操作放在逻辑分支中。
尽量避免在函数之前创建出函数所要使用到的所有对象。
2.String操作String字符串操作,我们多次使用到的。
所以在操作String的时候采用不高效的处理会一定程度上影响到程序的执行效率。
2.1. 我们认识一下StringString是不变类,如果我们使用“+”来连接字符串,会导致创建一个新的空间来存储连接后的字符串,在多次循环中使用“+”会导致内存循环被开辟。
这个时候应该使用StringBuilder。
StringBuilder内部有一个StringBuffer,连接操作不会每一次都分配新的字符串空间。
[2.2.字符串String对象的Length与0比较最快的,其次是String.Empty或空串C#在编译时将程序集中声明的所有字符串常量放到保留池中(intern pool),相同常量就不会重复分配了。
.NET跨平台应⽤MAUI介绍您可以使⽤ .NET 构建任何内容。
这是数百万开发⼈员选择 .NET 作为其职业⽣涯的平台,以及公司为其业务进⾏投资的主要原因之⼀。
通过 .NET 5,我们开始了统⼀ .NET 平台的旅程,将 .NET Core 和 Mono/Xamarin 整合在⼀个基类库(BCL)和⼯具链(SDK)中。
当我们考虑在统⼀的 .NET 中构建设备应⽤程序的外观时,我们看到许多设备跨多个平台使⽤,从 Android 和 iOS 到 Windows 和 macOS。
为了满⾜这⼀需求,我们很⾼兴地宣布⼀个新的⼀流的UI框架,这样做:.NET多平台应⽤程序UI,亲切地称为.NET MAUI。
让我们向您介绍 .NET MAUI 是什么、单个项⽬开发⼈员体验、现代开发模式,以及展望未来的旅程。
MAUI overview什么是 .NET MAUI.NET MAUI 是越来越受欢迎的 Xamarin.Forms ⼯具包的演进,本⽉将满 6 岁。
多年来,UPS、安永和达美等公司⼀直在利⽤Xamarin的移动专业知识,在.NET上为其业务提供动⼒;⼀些从⼀开始。
它还⾮常成功,帮助⼩型企业最⼤化其开发投资共享超过 95% 的代码,并击败竞争对⼿推向市场。
.NET MAUI 在移动设备上扩展了这⼀成功,以拥抱桌⾯,使其成为在两者(尤其是新设备(如新 Surface Duo)之间构建多平台应⽤程序的最佳⽅式。
.NET MAUI 简化了 .NET 开发⼈员的选择,提供了⽀持所有现代⼯作负载的单堆栈:Android、iOS、macOS 和 Windows。
在简单的跨平台 API 中,每个平台和 UI 控件的本机功能都触⼿可及,使您能够提供不折不扣的⽤户体验,同时共享⽐以前更多的代码。
单个项⽬开发⼈员体验.NET MAUI 的构建考虑到了开发⼈员的⼯作效率,包括开发⼈员所需的项⽬系统和跨平台⼯具。
.NET MAUI 将项⽬结构简化为单个项⽬,以定位多个平台。
Zuul和Gateway的区别及原理Zuul和Gateway是两种常用的微服务网关技术,它们在分布式系统中起到了重要的作用。
本文将对Zuul和Gateway进行比较,并详细介绍它们的原理。
一、Zuul的概述与原理Zuul是Netflix开发的一款基于Java的微服务网关系统。
作为Netflix的核心组件之一,Zuul被广泛应用于微服务架构中,扮演着请求路由和过滤功能的角色。
Zuul的原理基于Servlet容器,并通过使用Netflix的Ribbon来实现负载均衡。
它依赖于自定义的动态过滤器链,将请求分发至不同的微服务实例或后端服务器。
Zuul的主要特点包括动态路由、服务迁移支持、负载均衡以及请求和响应过滤。
通过动态路由,Zuul能够根据请求的URL将流量导向不同的后端服务。
服务迁移支持使得在服务发生变化时,可以无缝地将请求转移到新的服务上。
负载均衡通过Ribbon来实现,有效地分发请求至后端服务器。
请求和响应过滤则通过自定义的过滤器链实现,对传入的请求和传出的响应进行处理和过滤。
二、Gateway的概述与原理Gateway是Spring Cloud中的一项基于Spring WebFlux的反应式网关解决方案。
与Zuul相比,Gateway使用了响应式编程模型,可以支持更高的并发量和吞吐量。
Gateway的原理基于Spring Framework 5和Spring Boot 2,它使用了异步非阻塞编程的方式来实现请求路由和过滤。
Gateway支持声明式的路由规则和过滤规则,这使得开发人员可以轻松地定义路由和过滤器。
此外,Gateway还提供了集成与Spring Cloud服务发现、负载均衡和熔断器等功能。
三、Zuul和Gateway的区别1. 技术栈不同:Zuul是基于Servlet容器的,而Gateway则是基于Spring WebFlux和Netty的。
2. 编程模型不同:Zuul使用阻塞式编程模型,而Gateway使用响应式编程模型。
.net面试题及答案3篇.net面试题及答案11.JIT是什么,它是如何工作的?GC是什么,简述一下GC的工作方式?JIT:Just in time,C#或者是的代码首先被编译为IL存储在本地,当要运行这些代码的时候,CLR对IL进行第二次编译转换成机器码运行。
好处:可移植性,而且IL在加载到内存中时将受到类型安全性方面检查,这实现了更好的安全性和可靠性。
GC:垃圾回收(garbage collection),是根据程序的需要自动分配和回收内存的过程。
垃圾回收器处理的是引用对象,而且只回收堆上的内存。
这意味着假如维持对一个对象的引用,就会阻止GC重用对象使用的内存。
在.NET中,垃圾回收器采用的是mark-and-pact算法。
在一次垃圾回收周期开始的时候,它要识别对象的所有跟引用,根据这个引用可以遍历每个根引用所标识的一个树形结构,并递归确定所有引用指向的对象。
这样一来,垃圾回收器就可以识别所有可达的对象,在执行回收的时候,GC 不是枚举所有访问不到的对象,相反,通过压缩所有相邻的可达的对象来执行垃圾回收。
不可访问的对象就会被覆盖。
垃圾回收的宗旨是提高内存的利用率,它并不是用来清理文件句柄,和数据库连接字符串,端口或者其他有限的资源(终接器finalizer,不能被显示调用,不能传递任何参数,即不能被重载,只有垃圾回收器才能调用终接器,使用Using语句进行确定性终结2.类(class)和结构(struct)的区别是什么?它们对性能有影响吗?01. 值类型与引用类型结构是值类型:值类型在栈上分配地址,所有的基类型都是结构类型,例如:int 对应System.int32 结构,通过使用结构可以创建更多的值类型类是引用类型:引用类型在堆上分配地址堆栈的执行效率要比堆的执行效率高,可是堆栈的资源有限,不适合处理大的逻辑复杂的对象。
所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑因为结构是值类型所以结构之间的赋值可以创建新的结构,而类是引用类型,类之间的赋值只是复制引用注:1.虽然结构与类的'类型不一样,可是他们的基类型都是对象(object),c#中所有类型的基类型都是object2.虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用02.继承性结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的用sealed声明,可是结构是隐式的sealed .类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承注:虽然结构不能被继承可是结构能够继承接口,方法和类继承接口一样03.内部结构:结构:没有默认的构造函数,但是可以添加构造函数没有析构函数没有abstract 和sealed(因为不能继承)不能有protected 修饰符可以不使用new 初始化在结构中初始化实例字段是错误的类:有默认的构造函数有析构函数可以使用abstract 和sealed 有protected 修饰符必须使用new 初始化.net面试题及答案21.什么是元编程,.NET有哪些元编程的手段和场景?什么是反射?能否举一些反射的常用场景?有人说反射性能较差,您怎么看待这个问题?有什么办法可以提高反射的性能吗?学着做OA的时候,动态加载不同的DataProvider(Oracle和Sqlserver),方便,可以随时替换不用重新编译程序2.委托是什么?匿名方法是什么?在C#3.0中,Lambda表达式是什么?扩展方法是什么?LINQ是什么?您觉得C# 3.0中还有哪些重要的特性,它们带来了什么优势?BCL中哪些类库和这些特性有关?您*时最常用哪些?委托可以把一个方法作为参数代入另一个方法。
.NET中栈和堆的比较#1原文出处:/UploadFile/rmcochran/csharp_memory011220061 30034PM/csharp_memory.aspx尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(Garbage Collection),但是我们还是应该了解它们,以优化我们的应用程序。
同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。
在本文中我将讲解栈和堆的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作。
在.NET framework环境下,当我们的代码执行时,内存中有两个地方用来存储这些代码。
假如你不曾了解,那就让我来给你介绍栈(Stack)和堆(Heap)。
栈和堆都用来帮助我们运行代码的,它们驻留在机器内存中,且包含所有代码执行所需要的信息。
* 栈vs堆:有什么不同?栈负责保存我们的代码执行(或调用)路径,而堆则负责保存对象(或者说数据,接下来将谈到很多关于堆的问题)的路径。
可以将栈想象成一堆从顶向下堆叠的盒子。
当每调用一次方法时,我们将应用程序中所要发生的事情记录在栈顶的一个盒子中,而我们每次只能够使用栈顶的那个盒子。
当我们栈顶的盒子被使用完之后,或者说方法执行完毕之后,我们将抛开这个盒子然后继续使用栈顶上的新盒子。
堆的工作原理比较相似,但大多数时候堆用作保存信息而非保存执行路径,因此堆能够在任意时间被访问。
与栈相比堆没有任何访问限制,堆就像床上的旧衣服,我们并没有花时间去整理,那是因为可以随时找到一件我们需要的衣服,而栈就像储物柜里堆叠的鞋盒,我们只能从最顶层的盒子开始取,直到发现那只合适的。
[heapvsstack1.gif]以上图片并不是内存中真实的表现形式,但能够帮助我们区分栈和堆。
栈是自行维护的,也就是说内存自动维护栈,当栈顶的盒子不再被使用,它将被抛出。
相反的,堆需要考虑垃圾回收,垃圾回收用于保持堆的整洁性,没有人愿意看到周围都是赃衣服,那简直太臭了!* 栈和堆里有些什么?当我们的代码执行的时候,栈和堆中主要放置了四种类型的数据:值类型(Value Type),引用类型(Reference Type),指针(Pointer),指令(Instruction)。
1.值类型:在C#中,所有被声明为以下类型的事物被称为值类型:boolbytechardecimaldoubleenumfloatintlongsbyteshortstructuintulongushort2.引用类型:所有的被声明为以下类型的事物被称为引用类型:classinterfacedelegateobjectstring3.指针:在内存管理方案中放置的第三种类型是类型引用,引用通常就是一个指针。
我们不会显示的使用指针,它们由公共语言运行时(CLR)来管理。
指针(或引用)是不同于引用类型的,是因为当我们说某个事物是一个引用类型时就意味着我们是通过指针来访问它的。
指针是一块内存空间,而它指向另一个内存空间。
就像栈和堆一样,指针也同样要占用内存空间,但它的值是一个内存地址或者为空。
[heapvsstack2.gif]4.指令:在后面的文章中你会看到指令是如何工作的...* 如何决定放哪儿?这里有一条黄金规则:1. 引用类型总是放在堆中。
(够简单的吧?)(实体数据???)2. 值类型和指针总是放在它们被声明的地方。
(这条稍微复杂点,需要知道栈是如何工作的,然后才能断定是在哪儿被声明的。
)就像我们先前提到的,栈是负责保存我们的代码执行(或调用)时的路径。
当我们的代码开始调用一个方法时,将放置一段编码指令(在方法中)到栈上,紧接着放置方法的参数,然后代码执行到方法中的被“压栈”至栈顶的变量位置。
通过以下例子很容易理解...下面是一个方法(Method):public int AddFive(int pValue){int result;result = pValue + 5;return result;}现在就来看看在栈顶发生了些什么,记住我们所观察的栈顶下实际已经压入了许多别的内容。
首先方法(只包含需要执行的逻辑字节,即执行该方法的指令,而非方法体内的数据)入栈,紧接着是方法的参数入栈。
(我们将在后面讨论更多的参数传递)[heapvsstack3.gif]接着,控制(即执行方法的线程)被传递到堆栈中AddFive()的指令上,当方法执行时,我们需要在栈上为“result”变量分配一些内存,[heapvsstack5.gif]The method finishes execution and our result is returned. 方法执行完成,然后方法的结果被返回。
通过将栈指针指向AddFive()方法曾使用的可用的内存地址,所有在栈上的该方法所使用内存都被清空,且程序将自动回到栈上最初的方法调用的位置(在本例中不会看到)。
[heapvsstack7.gif]在这个例子中,我们的"result"变量是被放置在栈上的,事实上,当值类型数据在方法体中被声明时,它们都是被放置在栈上的。
值类型数据有时也被放置在堆上。
记住这条规则--值类型总是放在它们被声明的地方。
好的,如果一个值类型数据在方法体外被声明,且存在于一个引用类型中,那么它将被堆中的引用类型所取代。
来看另一个例子:假如我们有这样一个MyInt类(它是引用类型因为它是一个类类型):public class MyInt{public int MyValue;}然后执行下面的方法:public MyInt AddFive(int pValue){MyInt result = new MyInt();result.MyValue = pValue + 5;return result;}就像前面提到的,方法及方法的参数被放置到栈上,接下来,控制被传递到堆栈中AddFive()的指令上。
[heapvsstack8.gif]接着会出现一些有趣的现象...因为"MyInt"是一个引用类型,它将被放置在堆上,同时在栈上生成一个指向这个堆的指针引用。
在AddFive()方法被执行之后,我们将清空...[heapvsstack10.gif]我们将剩下孤独的MyInt对象在堆中(栈中将不会存在任何指向MyInt对象的指针!)这就是垃圾回收器(后简称GC)起作用的地方。
当我们的程序达到了一个特定的内存阀值,我们需要更多的堆空间的时候,GC开始起作用。
GC将停止所有正在运行的线程,找出在堆中存在的所有不再被主程序访问的对象,并删除它们。
然后GC会重新组织堆中所有剩下的对象来节省空间,并调整栈和堆中所有与这些对象相关的指针。
你肯定会想到这个过程非常耗费性能,所以这时你就会知道为什么我们需要如此重视栈和堆里有些什么,特别是在需要编写高性能的代码时。
引用类型,先释放他的指针,GC(垃圾处理器会处理实体的数据)。
Ok... 这太棒了, 当它是如何影响我的?Good question.当我们使用引用类型时,我们实际是在处理该类型的指针,而非该类型本身。
当我们使用值类型时,我们是在使用值类型本身。
听起来很迷糊吧?同样,例子是最好的描述。
假如我们执行以下的方法:public int ReturnValue(){int x = new int();x = 3;int y = new int();y = x;y = 4;return x;}我们将得到值3,很简单,对吧?假如我们首先使用MyInt类public class MyInt{public int MyValue;}接着执行以下的方法:public int ReturnValue2(){MyInt x = new MyInt();x.MyValue = 3;MyInt y = new MyInt();y = x;y.MyValue = 4;return x.MyValue;}我们将得到什么?... 4!为什么?... x.MyValue怎么会变成4了呢?... 看看我们所做的然后就知道是怎么回事了:在第一例子中,一切都像计划的那样进行着:public int ReturnValue(){int x = 3;int y = x;y = 4;return x;}[heapvsstack12.gif]在第二个例子中,我们没有得到"3"是因为变量"x"和"y"都同时指向了堆中相同的对象。
public int ReturnValue2(){MyInt x;x.MyValue = 3;MyInt y;y = x;y.MyValue = 4;return x.MyValue;}[heapvsstack13.gif]希望以上内容能够使你对C#中的值类型和引用类型的基本区别有一个更好的认识,并且对指针及指针是何时被使用的有一定的基本了解。
在系列的下一个部分,我们将深入内存管理并专门讨论方法参数。
To be continued....NET中栈和堆的比较#2原文出处:/UploadFile/rmcochran/csharp_memory2B0114200 6125918PM/csharp_memory2B.aspx尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(Garbage Collection),但是我们还是应该了解它们,以优化我们的应用程序。
同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。
在本文中我将讲解我们必须要注意的方法传参的行为。
在第一部分里我介绍了栈和堆的基本功能,还介绍到了在程序执行时值类型和引用类型是如何分配的,而且还谈到了指针。
* 参数,大问题这里有一个代码执行时的详细介绍,我们将深入第一部分出现的方法调用过程...当我们调用一个方法时,会发生以下的事情:1.方法执行时,首先在栈上为对象实例中的方法分配空间,然后将方法拷贝到栈上(此时的栈被称为帧),但是该空间中只存放了执行方法的指令,并没有方法内的数据项。
3.方法参数的分配和拷贝是需要空间的,这一点是我们需要进一步注意。
示例代码如下:public int AddFive(int pValue){int result;result = pValue + 5;return result;}此时栈开起来是这样的:就像第一部分讨论的那样,放在栈上的参数是如何被处理的,需要看看它是值类型还是引用类型。
值类型的值将被拷贝到栈上,而引用类型的引用(或者说指针)将被拷贝到栈上。