混着混着又开始迷惑了...大家帮帮忙

tantj 2008-01-10 06:36:44

static void Square(int x)
{
// code...
}

static void Square(ref int x)
{
// code...
}


上面的方法是按值传递,下面是按引用传递

如果在一个类里面

public class TestClass
{
public int a;
}


那么

static void Square(TestClass x)
{
x.a = 123;
}

void Main()
{
TestClass tc = new TestClass();
tc.a = 111;
Square(tc);
}


当使用Square方法时,tc还是按值传递的,只是传递了它引用,因为引用类型的变量的值本身是一个引用。
当使用ref或者out的时候(static void Square(ref TestClass x)),tc才是按引用传递。
不知道我这样理解对不对?
...全文
445 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
jinjunmax_78 2008-01-11
  • 打赏
  • 举报
回复
我也是这么认为的。
就像msdn里说的“按引用传递值类型是有用的,但是 ref 对于传递引用类型也是很有用的。这允许被调用的方法修改该引用所引用的对象,因为引用本身是按引用来传递的。下面的示例显示出当引用类型作为 ref 参数传递时,可以更改对象本身”。
草原可可 2008-01-11
  • 打赏
  • 举报
回复
楼主也是理解正确的
GhostAdai 2008-01-11
  • 打赏
  • 举报
回复
13楼的大作我们都收到了!
stning 2008-01-11
  • 打赏
  • 举报
回复
13楼解释得非常的清楚
ahshow 2008-01-11
  • 打赏
  • 举报
回复
13楼说得很好,其实大致理解就行了。
changjiangzhibin 2008-01-11
  • 打赏
  • 举报
回复
长安米贵,居亦弗易
tantj 2008-01-11
  • 打赏
  • 举报
回复
15楼的代码我自己也试过...在公司每到下班前人就有点神志不清了
hapen_zhang 2008-01-11
  • 打赏
  • 举报
回复
ref表示的就是进去子函数之后做的改动在函数结束之后都不生效,
传的应该如楼上大家所说的只是个副本
Jimonline 2008-01-11
  • 打赏
  • 举报
回复
上程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass(1);
TestClass originalTC = tc;

Console.WriteLine("The original tc...");
Console.WriteLine(string.Format("tc.Number={0}.", tc.Number));
Console.WriteLine();

Program p = new Program();
p.ModifyTestClass(tc);

Console.WriteLine("After calling ModifyTestClass()...");
Console.WriteLine(string.Format("tc.Number={0}.", tc.Number));
Console.WriteLine(string.Format("Does the current tc equal to the original tc? Answer: {0}", (tc == originalTC)));

Console.WriteLine();
Console.WriteLine("After calling ModifyTestClassRef()...");
p.ModifyTestClassRef(ref tc);
Console.WriteLine(string.Format("tc.Number={0}.", tc.Number));
Console.WriteLine(string.Format("Does the current tc equal to the original tc? Answer: {0}", (tc == originalTC)));

Console.ReadKey();
}

public void ModifyTestClass(TestClass tc)
{
tc = new TestClass(2);
}

public void ModifyTestClassRef(ref TestClass tc)
{
tc = new TestClass(2);
}
}

class TestClass
{
public TestClass(int number)
{
Number = number;
}

public int Number = 0;
}
}


结果:
The original tc...
tc.Number=1.

After calling ModifyTestClass()...
tc.Number=1.
Does the current tc equal to the original tc? Answer: True

After calling ModifyTestClassRef()...
tc.Number=2.
Does the current tc equal to the original tc? Answer: False
tantj 2008-01-11
  • 打赏
  • 举报
回复
解释的非常清楚,谢谢了
Q_282898034 2008-01-10
  • 打赏
  • 举报
回复
TestClass tc = new TestClass();

口头上,我们经常说 tc 是个引用类型对象。
就像我有一张名片(tc),名片上写着 威海路142号(tc的值),通过它可以找到我的一幢房子(对象)

Square(tc);

这里传递的 tc 不是托管堆上的对象体,而是一个地址值的副本,该值指向托管堆里那个对象。
就像我把我家地址的名片复印了一张给你。不过你怎么修改那个名片副本,例如改写为“利津路27号”,都不会影响到我,我手里握着最原始的名片(tc),我随时可以找到那幢房子(对象),但你能够把房子拆了,我虽然不会搞错那幢房子在哪,但你的大作我会收到。
我们把它叫做值引用。
如果不是 tc 这样的引用类型变量,而是int i = 10 这种值类型变量,我传递给你的是 i 的值的副本,你怎么修改那个副本都不会对我有影响。

Square(ref tc);

这里传递的也是一个地址值的副本,该值指向堆栈上的那个变量 tc,而 tc 指向那个托管堆里的对象体。
我这里提到了堆栈,那么我们假设我的名片盒就是那个堆栈,名片就是堆栈上各个变量。
现在我给你第1张名片(ref tc)的复印件,名片上印着“第5张名片”(ref tc 的值),你可以继续找到第5张名片(堆栈上的 tc 变量),通过第5张名片你又会找到这幢房子(托管堆上的对象体)。如果你找到第5张名片,并且修改第5张名片的内容为“利津路27号”,这样我就会找不到我的那幢房子,而把另外一幢房子当成我的房子。如果你不修改第5张名片而把我的那幢房子拆了,我也会收到你的大作。
我们把它叫做参数的引用传递。
同样,如果不是 tc 这样的引用类型变量,而是int i = 10 这种值类型变量,我传递给你的是 i 的地址值,你通过地址值找到 i,对 i 进行修改,我也会收到。

Square(out tc);

这个和上面的 ref 唯一区别是,可以不给 tc 赋值就开始用。
例如上例,我给你第1张名片的副本写着“第5张名片”,但第5张名片上什么也没写,你可以写上“威海路142号”,然后我就可以找到那幢房子。
对于值类型变量,你同样可以改写该变量的值让我知道。
psychese 2008-01-10
  • 打赏
  • 举报
回复
LZ编译了用IL DASM看一下就知道了
tantj 2008-01-10
  • 打赏
  • 举报
回复
呵呵,我觉得7楼那种说法挺好理解的
eyesinbook 2008-01-10
  • 打赏
  • 举报
回复
我总觉得楼主的说法不妥当,2楼的说法要规范些
可惜我自己又说不出什么,纯粹是编程的一种感觉,进来学习了
shao99 2008-01-10
  • 打赏
  • 举报
回复
我觉得Square(ref TestClass x)一般用于x需要变更的时候
而当x的属性变化则不需要ref
stray2010 2008-01-10
  • 打赏
  • 举报
回复
值是传一个值相同的附本,而引用传的内存地址
顶.........
Efcndi 2008-01-10
  • 打赏
  • 举报
回复
呵呵。之所以我的看法和上面的朋友包括LZ有点分歧。

是从不同的角度来看“值”。

1、把实际的TestClass对象看成值,那么Square(TestClass x)传递的是一个引用。

2、把Square(TestClass x)中的x看成一个引用,那么传递的是一个值。

这个只是角度的区别。
但是更规范的说法应该是LZ正确的。
ProjectDD 2008-01-10
  • 打赏
  • 举报
回复
值为引用,的转换就是所谓之,装箱,和折箱 box unbox 的操作,楼上说的
好象不是很妥当

值是传一个值相同的附本,而引用传的内存地址.
Efcndi 2008-01-10
  • 打赏
  • 举报
回复
“按值传递的,只是传递了它引用,因为引用类型的变量的值本身是一个引用”

LZ的说法更合理吧。角度不同。
引用本身也是一个值,值也可以表示一个引用。
taiyangyu119 2008-01-10
  • 打赏
  • 举报
回复
对,当不加ref或out的时候传递的是值类型或者引用类型的按值传递,当使用ref或out的时候是值类型或者引用类型的按引用传递,星星们,我的表述没错吧
加载更多回复(3)

111,094

社区成员

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

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

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