C#引用类型赋值的基础问题

josxhn 2010-07-19 10:15:22
代码如下,问题是:Test应该算是引用类型吧,在method()中对t赋值的时候

t = _t; 是不是仅仅是将 t 的指针指向了 _t ?按说 _t 是个局部变量,退出 method() 方法后 t 的指向就应该无效了,可是我用MessageBox.Show(t.str);测试发现 t 的指向仍然是有效的。

t = _t; 和 t = new Test(_t); 有什么区别?


namespace test_AssignOfReferenceType
{
public partial class Form1 : Form
{
public Test t;

public Form1 ()
{
InitializeComponent ();

}

private void toolStripButton1_Click (object sender , EventArgs e)
{
Test _t=new Test();
method (_t);
MessageBox.Show (t.str);
}

public void method (Test _t)
{
//t是引用类型,测试对它的赋值是否需要用new
//这里看来不需要用new,直接=复制就可以
//那么和用new来赋值有什么区别?
t = _t;
//t = new Test(_t);


}
}

public class Test
{
public string str;
public Test () { str = "xxx"; }
public Test (Test t) { str = t.str; }
}
}
...全文
231 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
请叫我卷福 2010-07-21
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 josxhn 的回复:]
楼上几位的意思我大概明白了,new Test()被创建在堆上,在函数内t指向new Test()后,离开了函数t的指向仍然有效。

但是关键是这段代码:

C# code

public void method (Test _t)
{
//t是引用类型,测试对它的赋值是否需要用new
……
[/Quote]
_t是引用类型 不是说_t分配在堆上 只是_t指向的对象分配在堆上 _t还是在栈上
t=_t; 之后 t 和 _t 指向堆上同一个对象
函数结束后 不管_t有没有效(当然这里_t失效了) 成员t一直有效(因为t是对象成员,生命期跟对象同存) t指向的对象也一直有效(直到t没效了,垃圾回收器回收)。。。
josxhn 2010-07-21
  • 打赏
  • 举报
回复
楼上几位的意思我大概明白了,new Test()被创建在堆上,在函数内t指向new Test()后,离开了函数t的指向仍然有效。

但是关键是这段代码:
        
public void method (Test _t)
{
//t是引用类型,测试对它的赋值是否需要用new
//这里看来不需要用new,直接=复制就可以
//那么和用new来赋值有什么区别?
t = _t;
}


按照 wuyazhe 兄的说法:
“_t 是Test类型引用,按理说引用类型都被放在堆上,但不确定,因为离开函数就无效的,是交给垃圾回收来处理_t还是直接分配到栈上直接出栈回收。”
我测试的结果,函数结束后,t的指向仍然有效,这是怎么回事呢?
hwbox 2010-07-19
  • 打赏
  • 举报
回复

test _t = new test();
中一个new test()创建的对象(对象1)在堆中创建并由 _t 引用。


test t = new test();
中一个new test()创建的对象(对象2)在堆中创建并由 t 引用。


t = _t
时t失去了对对象2的引用,开始引用对象1。(我个人估计对象2,已经是可销毁的了,不定什么时候就被垃圾收集了。)
卧_槽 2010-07-19
  • 打赏
  • 举报
回复
你可以再调试器中查看
t = _t;
//t = new Test(_t);
这两种方式后,t的gethashcode方法值,默认该方法的值是当前对象的首地址值。
就明白有什么不同了。
卧_槽 2010-07-19
  • 打赏
  • 举报
回复
引用对象的指针地址是存放在栈内存中
new 一个对象的时候,会在栈内存中分配一个指针地址空间,存放堆内存中的一个地址值。这个值就是这个对象的首地址。
如果是=赋值的话,是不会开辟新的栈内存空间,而是把=右边的指针地址值赋给这个空间。
Peter200694013 2010-07-19
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 peter200694013 的回复:]
如果构造函数Test(Test _t)
这么定义:
public Test(Test _t)
{
this = _t;
}
//则不会在堆中生成新对象,还是两个引用变量指向堆中同一个对象
[/Quote]
so sorry
this 是read-only的,这个是错误的(抱歉)
兔子-顾问 2010-07-19
  • 打赏
  • 举报
回复
Test _t=new Test();
这里有2个对象被创建:
new Test() 被创建在堆上
_t 是Test类型引用,按理说引用类型都被放在堆上,但不确定,因为离开函数就无效的,是交给垃圾回收来处理_t还是直接分配到栈上直接出栈回收。
t是成员变量
t指向new Test()这个对象,函数退出,_t被释放,但new Test()依然存在。
Peter200694013 2010-07-19
  • 打赏
  • 举报
回复
如果构造函数Test(Test _t)
这么定义:
public Test(Test _t)
{
this = _t;
}
//则不会在堆中生成新对象,还是两个引用变量指向堆中同一个对象
Peter200694013 2010-07-19
  • 打赏
  • 举报
回复
[Quote=引用楼主 josxhn 的回复:]
public void method (Test _t)
{
//t是引用类型,测试对它的赋值是否需要用new
//这里看来不需要用new,直接=复制就可以
//那么和用new来赋值有什么区别?
t = _t;
//t = new Test(_t);


}
[/Quote]
t = _t;// 两个引用变量指向堆中的同一个对象
如果是t = new Test(_t); 则是会在堆中重新生成一个对象

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧