关于C#中引用类型参数传递行为的困惑及代码疑问
为什么两段C#代码的输出结果不同?
先看你给出的两段代码及对应结果:
第一段代码
public class TestClass { public int x; public int y; public TestClass(int xx, int yy) { this.x = xx; this.y = yy; } } void tfn(TestClass a) { a = new TestClass(3, 4); } tfn(c); Console.WriteLine($"c.x: {c.x}.");
运行结果:c.x: 1.
第二段代码
void tfn(TestClass a) { TestClass b = a; b.x = 3; } tfn(c); Console.WriteLine($"c.x: {c.x}");
运行结果:c.x: 3.
核心概念澄清
C#里所有参数传递都是按值传递,这是理解差异的关键。对于自定义类这类引用类型,变量存储的是对象在堆内存中的地址(即"引用")。当你把引用类型变量作为参数传入方法时,传递的是这个引用的副本——不是对象本身,也不是原变量的引用。
第一段代码分析
假设调用tfn(c)前,c是new TestClass(1, 2),此时c保存着指向该对象的内存地址(比如0x123):
- 调用
tfn(c)时,参数a会得到c中引用的副本,也就是a也指向0x123对应的对象。 - 在
tfn方法里执行a = new TestClass(3, 4),这是给局部变量a重新赋值,让它指向一个新创建的对象(内存地址比如0x456)。 - 这个操作只修改了方法内部的
a变量,完全不影响外部的c——c依然指向原来0x123的对象,所以输出c.x: 1。
第二段代码分析
同样,调用tfn(c)前c指向0x123的对象:
- 调用
tfn(c)时,参数a得到c引用的副本,同样指向0x123的对象。 TestClass b = a;让b也保存这个引用,所以b、a、c都指向同一个堆上的对象。b.x = 3;是通过引用修改了堆上对象的x属性,这个修改直接作用于对象本身,而非变量。- 外部的
c依然指向这个对象,所以输出时会看到修改后的x值3。
总结差异
- 第一段代码是修改参数变量的引用指向:仅改变方法内局部变量的指向,和外部变量无关。
- 第二段代码是通过引用修改对象的内部数据:所有指向该对象的变量都会感知到这个变化。
内容的提问来源于stack exchange,提问作者user8677843
相关产品推荐
相关产品推荐

