Reference in C#

关于C#里的引用一直没有个清楚的认识,特别是对应传参时ref的运用。现在试着了解一下以理清概念。

首先,我们都知道在C#里有两种类型:值类型与引用类型。

对于值类型比较简单,如果作为参数传递时是拷贝传入,所以说在函数里改变参数是不会修改源数据。如果要同时修改源数据,就可以加上ref。

对于引用类型就比较麻烦。首先,所有的类在C#中都是引用。但是其中string类是奇怪的,虽然string类是引用,但是由于一旦给string赋值,那么它的值是不能修改的,所以在给string改值时,其实是重新给string指向一个新的地址, 因此要想改变原值就需要加上ref。

至于其他的类,什么时候要加ref,什么时候不需要加ref呢?

一个类作为参数传递是其实传递的是它的引用,其引用指向这个类的内存。因此无论函数里外,这个引用都是指向同一个内存, 所以如果只是想修改这个内存你的值可以直接修改,不需要加ref。但是如果要修改这个引用所指向的内存,就是说让这个引用指向新的内存(比如是new操作),那这时就需要加上ref才能保证传入的参数能被改变。

简单的列子,我们来试着交换两个引用值:

//测试类
class Test
{
     public string Name {get;set}  
}

//测试函数1
void Swap_without_ref(Test test1, Test test2)
{
     Test _t = test1;
     test1 = test2;
     test2 = _t;        
}

//测试函数2
void Swap_with_ref(ref Test test1, ref Test test2)
{
     Test _t = test1;
     test1 = test2;
     test2 = _t;        
}

static void Main()
{
  Test test1 = new Test{ Name = "a" };
  Test test2 = new Test{ Name = "b" };
  
  Swap_without_ref(test1, test2); //test1,test2的值没有改变
  Swap_with_ref(ref test1, ref test2); //test1,test2的值相互交换了
}

接下来我们把Test类改一下, 这回我们只改Test类中包含的类Case。

//测试类
class Case
{
     public string Name {get;set;}
}

class Test
{
     public string Name {get;set;}  
     public Case  Case {get;set;}
}

//测试函数1
void Swap_Case(Test test1, Test test2)
{
     test1.Case = test2.Case       
}

static void Main()
{
  Test test1 = new Test{ Name = "a" , new Case{ Name = "a" }};
  Test test2 = new Test{ Name = "b" , new Case{ Name = "b" } };
  
  Swap_Case(test1, test2); //test1的case值改变
}
posted @ 2013-03-21 10:46  谷满仓  阅读(322)  评论(0)    收藏  举报