我们知道.Net框架中,对象的类型可以分为值类型和引用类型2种。所有的引用类型都继承自System.Object,所有的值类型都继承自System.ValueType。值类型和引用类型在内存的分配、数据结构、操作上会有很大的不同,在这里我简单说下值类型与引用类型在参数传递时的不同之处(欢迎大家拍砖,小弟欲练钢筋铜骨,越拍神功越厉害 :))。
     我们先来看下面一个函数,这个函数的目的是交换2个object对象。
/// <summary>
/// 交换2个object对象
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>

public static void Swap(object p1,object p2)
{
    
//declare
    object m=new object();
    
//swap
    m=p2;
    p2
=p1;
    p1
=m;
}

      哦,满天的臭鸡蛋和西红柿向我砸来了,为什么要砸我啊?恩,让我们写个单元测试测试一下这个方法
using

namespace TestProgrammerLife
{
    
/// <summary>
    
/// 测试交换助手
    
/// </summary>

    [TestFixture]
    
public class TestSwapHelper
    
{
        
constructor

        
test methods

        
nested class
    }

}

     满怀信心的点了NUnit的Run按钮,红条。为什么啊,引用类型不是存放指向对象的指针吗(当然还包括指向类型方法表的指针以及进行同步控制的成员)?为什么会交换不成功呢?
        为了查明原因,我们先来了解下在参数传递的时候系统会做些什么。当我们调用SwapHelper.Swap(),并把2个object对象h1,h2传递给方法,这时候系统首先会copy h1和h2,然后copy获得的2个object对象传递给方法SwapHelper.Swap方法去调用(值传递--C#中默认的参数传递方式)。那么我们调用SwapHelper.Swap,系统完成参数传递后会产生什么样的情景呢?让我们看下面这幅图

      也就是说,关键点在于在参数传递时,系统做个copy动作,如果目标实例是引用类型,那么拷贝的就是指向引用类型实例的指针(当然还包括指向类型方法表的指针以及进行同步控制的成员),如果是值类型,那么拷贝的就是值类型的实例,这其实是一个内存拷贝。知道问题所在了,那么修改就很简单了,把SwapHelper.Swap(object,object)方法的签名改为SwapHelper.Swap(ref object,ref object)就可以实现我们希望的功能了。
     其实,对于引用类型来说,如果不对引用类型对象本身(很拗口,这里的意思指引用类型对象的指针部分)进行赋值操作而仅仅操作它指向的实例,那么值传递与引用传递没有区别。

posted on 2006-12-12 17:07  东风31  阅读(203)  评论(0)    收藏  举报