引用传递的参数类型,加不加ref是不同的

来源:互联网 发布:鹰扬拜占庭 知乎 编辑:程序博客网 时间:2024/05/16 05:31
 教科书上说引用传递的参数引用时,加不加ref都可以,都会改变参数原来的值,值传递参数引用时如果想要改变原来的值,必须加ref。以前遇到的大部分情况确实是如此,引用传递类型比如ArrayList,DataTable到另一个方法中,并在该方法中改变参数值,原调用方法处的变量确实改变了。但是今天遇到一个问题,引用的DataTable如果不加ref关键字,调用方法改变其值后却不变,而加上ref关键字后改值却变了,示例代码如下: 

private void button1_Click(object sender, System.EventArgs e)
  {
   DataTable dt = new DataTable();
   changearray( dt);   调用方法改变其值后,dt仍然没有数据
  
  }  

private void changearray( DataTable dtRef)
  {
   DataTable dtlist = new DataTable();
   dtlist.Columns.Add("A",typeof(string));
   DataRow dr = dtlist.NewRow();
   dr["A"] = "9999999999";
   dtlist.Rows.Add(dr);
   dtRef = dtlist.Copy();
              
  }

加上ref关键字后:

private void button1_Click(object sender, System.EventArgs e)
  {
   DataTable dt = new DataTable();
   changearray( ref dt);   调用方法改变其值后,dt中有数据了  
  }  

private void changearray( ref DataTable dtRef)
  {
   
   dtlist.Columns.Add("A",typeof(string));
   DataRow dr = dtlist.NewRow();
   dr["A"] = "9999999999";
   dtlist.Rows.Add(dr);
   dtRef = dtlist.Copy();
  }

更奇怪的是,如下调用方法,无论加不加ref都是可以改变值的:

private void button1_Click(object sender, System.EventArgs e)
  {
   DataTable dt = new DataTable();
   changearray( dt);
  
  }

  private void changearray( DataTable dtRef)
  {   
   dtRef.Columns.Add("A",typeof(string));
   DataRow dr = dtRef.NewRow();
   dr["A"] = "9999999999";
   dtRef.Rows.Add(dr);        
  }

       百思不得其解,查了很多资料,基本上都是认为引用传递类型加不加ref都是一样的,可以目前发现的问题是明明不一样。后来网上搜到了遇到同一问题的帖子,虽然没有对该现象权威的解释,但是基本明白了出现问题的根源。

      传递引用 和传递 ref 引用的区别,是第一个传递指针,第二个是传递指向指针的指针,所以第一个可以修改那个指针指向的内容,但不能修改指针本身的地址,第二个则可以修改指针地址

传递引用 和传递 ref 引用的区别,学过C++的话应该很好理解.
就是指针(*)和引用(&)的区别.
void mothod(DataTable dt) 传递的是dt变量所指向的内存空间
void mothod(ref DataTable dt) 传递的是dt变量本身的内存地址

这里可能是作用域的问题
在changearray方法里面如果不使用dt=new DataTable()语句,则在changearray中处理dt,button1_Click里的dt都会变化,
因为button1_Click()里的dt和changearray里的dt是DataTable类的同一个实例,只是在changearray中改变了它的值,作用域在button1_Click()中没有发生变化。
如果在changearray中有dt=new DataTable()语句,相当于重新定义DataTable类的新实例,此dt已非彼dt,
dt的作用域此时只在changearray中有效,也就是说changearray中的dt根本和button1_Click里面的dt已不是同一个实例,在changearray里面根本就没有对button1_Click()里面的dt做任何改变。

所以可以预见的语句:dtRef = dtlist.Copy();对dtRef 进行了重新初始化处理,所以如果不加ref时,dtRef就被重新定义了,dtRef所指向的地址与原dt不同了。如果加上ref引用时,因为传递的变量所在的地址,dtRef虽然重新定义了,不管其变量地址指向哪里,因为传递了dt的所在地址,其值仍然是可以得到的。

原创粉丝点击