.Net 框架程序设计(4)
来源:互联网 发布:介绍云计算的ppt 编辑:程序博客网 时间:2024/05/29 19:28
1 值传递和引用传递
值传递是传递的值的拷贝;引用传递是传递的对象本身。
测试代码:
classProgram { staticvoid Main(string[] args) { SomeValueType valueParam; SomeRefType refParam = new SomeRefType(); //***** <1> **** valueParam.Name = "before excute"; Console.WriteLine("值类型作参数,执行前:{0}", valueParam.Name); Test.DoSomething(valueParam); Console.WriteLine("值类型作参数,执行后:{0}", valueParam.Name); Console.WriteLine(""); //***** <2> **** refParam.Name = "before excute"; Console.WriteLine("引用类型作参数,执行前:{0}", refParam.Name); Test.DoSomething(refParam); Console.WriteLine("引用类型作参数,执行后:{0}", refParam.Name); Console.WriteLine(""); //***** <3> **** valueParam.Name = "before excute"; Console.WriteLine("值类型作参数,执行前:{0}", valueParam.Name); Test.DoOtherSomething(valueParam); Console.WriteLine("值类型作参数,执行后:{0}", valueParam.Name); Console.WriteLine(""); //***** <4> **** refParam.Name = "before excute"; Console.WriteLine("引用类型作参数,执行前:{0}", refParam.Name); Test.DoOtherSomething(refParam); Console.WriteLine("引用类型作参数,执行后:{0}", refParam.Name); Console.WriteLine(""); //***** <5> **** valueParam.Name = "before excute"; Console.WriteLine("值类型引用传递,执行前:{0}", valueParam.Name); Test.DoSomething(ref valueParam); Console.WriteLine("值类型引用传递,执行后:{0}", valueParam.Name); Console.WriteLine(""); //***** <6> **** refParam.Name = "before excute"; Console.WriteLine("引用类型引用传递,执行前:{0}", refParam.Name); Test.DoSomething(ref refParam); Console.WriteLine("引用类型引用传递,执行后:{0}", refParam.Name); Console.WriteLine(""); //***** <7> **** valueParam.Name = "before excute"; Console.WriteLine("值类型引用传递,执行前:{0}", valueParam.Name); Test.DoOtherSomething(ref valueParam); Console.WriteLine("值类型引用传递,执行后:{0}", valueParam.Name); Console.WriteLine(""); //***** <8> **** refParam.Name = "before excute"; Console.WriteLine("引用类型引用传递,执行前:{0}", refParam.Name); Test.DoOtherSomething(ref refParam); Console.WriteLine("引用类型引用传递,执行后:{0}", refParam.Name); Console.WriteLine(""); Console.ReadKey(); } } classSomeRefType { publicstring Name; } structSomeValueType { publicstring Name; } classTest { publicstaticvoid DoSomething(SomeValueType v) { v.Name = "value type param"; Console.WriteLine("值类型作参数,执行中:"+v.Name); } publicstaticvoid DoSomething(SomeRefType r) { r.Name = "ref type param"; Console.WriteLine("引用类型作参数,执行中:" + r.Name); } publicstaticvoid DoOtherSomething(SomeValueType v) { v = new SomeValueType(); v.Name = "change value type param"; Console.WriteLine("引用类型作参数,执行中:" + v.Name); } publicstaticvoid DoOtherSomething(SomeRefType r) { r = new SomeRefType(); r.Name = "change ref type param"; Console.WriteLine("引用类型作参数,函数内创建对象,执行中:" + r.Name); } publicstaticvoid DoSomething(refSomeValueType v) { v.Name = "value type param with ref"; Console.WriteLine("引用传递值类型,执行中:" + v.Name); } publicstaticvoid DoSomething(refSomeRefType r) { r.Name = "ref type param with ref"; Console.WriteLine("引用传递引用类型,执行中:" + r.Name); } publicstaticvoid DoOtherSomething(refSomeValueType v) { v = new SomeValueType(); v.Name = "create value type param with ref "; Console.WriteLine("引用传递值类型,函数内建对象,执行中:" + v.Name); } publicstaticvoid DoOtherSomething(refSomeRefType r) { r = new SomeRefType(); r.Name = "create ref type param with ref"; Console.WriteLine("引用传递引用类型,函数内创建对象,执行中:" + r.Name); } }
2 代码分析
2.1 值参数<1>
从运行后的结果来看,值类型参数在传递进函数前后没有任何变化,也就是说对形参的修改没有影响实参。
从内存分配上看,值类型参数分配在线程栈上,形参是对实参的完全拷贝。实参和形参都有各自的地址空间,两者间没有任何关联。
2.2 引用参数<2><4>
从运行后的结果来看,引用类型参数在传递进函数前后发生了变化,也就是说对形参的修改直接影响了实参的值。
从内存分配上看,引用类型参数分配在托管堆上,而保持这个对象的引用存放在线程栈上。因为实参保存的是该对象在托管堆中的地址,所以传给形参的也是这个地址,这样形参和实参都保存了相同的地址引用,他们同时指向了同一个对象地址,在函数内部如果vp不创建对象,对形参的修改会直接反映到实参上。
如果在函数内部形参rp又创建了新的对象,则内存分配如下:
从上图可以看出rp指向了另一个创建的对象,形参和实参没有了关联,此时再次对形参进行修改,修改不会影响到实参。
2.3 值类型引用传递
从运行后的结果来看,值类型参数在传递进函数前后发生了变化,也就是说对形参的修改直接影响了实参的值。
从内存分配上看,传给形参的是实参在线程堆栈上的地址,形参指向的其实仍然是实参所在的位置,两者完全同步。
2.4 引用类型引用传递<6><8>
从运行后的结果来看,引用类型参数在传递进函数前后发生了变化,也就是说对形参的修改直接影响了实参的值。
从内存分配上看,和值类型的引用传递在堆栈上的形式有一定的相似,形参保存的是实参的地址,形参并没有指向对象在托管堆上的地址,而是指向了实参,和实参共同拥有一个指向该对象内存中的引用。
如果在函数内部形参rp又创建了新的对象,则内存分配如下:
和<2><4>对照比较,在加上ref后,实参和形参自始至终都具有相同的引用。
总结:1)值传递是对目标对象的值拷贝(无论是值类型和引用类型对象,引用类型的值拷贝是拷贝的对象在托管堆中的地址)。
2)引用传递是传递的目标对象本身,才是真正的引用传递(相对于引用类型传递)。
最终的运行结果全图如下:
- .Net 框架程序设计(4)
- (.net)框架的程序设计
- .Net 框架程序设计(1)
- .Net 框架程序设计(2)
- .Net 框架程序设计(3)
- .Net 框架程序设计(6)
- .Net 框架程序设计(5)
- 《Microsoft .NET框架程序设计(修订版)》
- 书评《Microsoft .NET框架程序设计(修订版)》
- Microsoft .NET框架程序设计读书笔记(一)
- [《.net框架程序设计》]前言
- 《.NET框架程序设计》前言
- 《.net框架程序设计》学习
- .net 框架程序设计
- .net 框架程序设计
- .net 框架程序设计 读书笔记(一)---.net 平台构成
- .net 框架程序设计 读书笔记(一)---.net 平台构成
- .net框架程序设计读书笔记系列
- 使用 Android快速开发框架 Afinal 0.3 快速开发网络应用相关APK
- C#拆箱与装箱之代码优化
- 信号与系统6:差分微分表示系统
- poj 1384完全背包
- Error generating final archive: Debug Certificate expired on 解决
- .Net 框架程序设计(4)
- 石子合并 (区间dp)
- 一些网站资源博客
- 球队对手排序问题(java面向对象代码解)
- 256色工具栏使用截图
- Magento admin system config 写好后注意事项
- 下载:郑文强的测试课件PPT与视频资料
- 回答网友一个wince 的编译错误问题
- LINUX学习之路----shell编程