You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中object为引用类型,修改方法内参数后外部原值为何不变

现象原因

这个问题的核心是两个容易混淆的C#语法特性:引用类型的参数默认按值传递,以及值类型的装箱逻辑,具体拆解如下:

  • 首先明确C#的参数传递规则:所有参数默认都是按值传递,即便参数类型是引用类型也不例外。所谓「引用类型传递的是对象引用」指的是传递的值本身是引用地址,但这个引用地址是从原变量复制出来的副本,和原变量是两个独立的存储单元。
  • 第一步object o=100执行时,因为int是值类型,赋值给引用类型object会触发装箱操作:在堆内存中生成一个包装了100的装箱对象,栈上的变量o存储的是这个装箱对象的内存地址。
  • 调用ChangeReferenceObj(o)时,会把o存储的地址复制一份传给形参a,此时a和o指向同一个堆上的100装箱对象,因此方法内第一次输出e100符合预期。
  • 执行a=500时,会生成一个新的包装了500的装箱对象,然后把新对象的地址赋值给形参a。注意这里修改的是形参a本身存储的地址值,而a是o的副本,二者是独立的栈变量,修改a的指向完全不会影响外部o的指向,o仍然指向原来的100装箱对象。

补充:如果你在方法内不是给a整体赋值新对象,而是修改a指向的对象的成员属性/字段,外部变量会同步变化,因为二者此时仍然指向同一个堆对象。只有修改形参本身的指向(也就是给形参整体赋值新对象)才不会同步到原变量。

  • 方法执行结束回到Main方法后,o的指向没有发生任何变化,因此最终输出d100。

复现预期效果的方案

如果希望修改形参指向后同步修改外部变量,需要使用ref关键字声明按引用传递:

// 修改方法声明,添加ref关键字
static void ChangeReferenceObj(ref object a) 
{
    Console.WriteLine("e"+a); 
    a=500; 
    Console.WriteLine("f"+a);
}

// 调用时也需要添加ref关键字
ChangeReferenceObj(ref o);

此时传递的不再是引用的副本,而是外部变量o本身的存储地址,修改形参a的指向等价于直接修改外部o的指向,最终会输出d500。

内容的提问来源于stack exchange,提问作者Tommy1987

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:57:02