为何代码中c = null不生效?如何将对象设为null?
为什么
c = null 不生效?如何将对象设为 null? 咱们先拆解你遇到的问题,核心在于C#里引用类型的参数传递逻辑,以及ref关键字的作用。
1. 为什么g方法里的c = null没效果?
先看你代码里的g方法:
static void g(Sample c){ c = null; }
当你在Main里调用g(c)时,这里传递的是引用的副本——也就是说,g方法里的参数c是一个全新的变量,它和Main里的c指向同一个Sample对象,但本身是两个独立的引用。
当你在g里执行c = null,只是把这个局部参数引用指向了null,完全不会影响Main里原来的那个引用。所以Main里的c依然指向之前创建的Sample对象,它的c成员还是2,这就是最后输出2的原因。
而f方法里的c.c = 2能生效,是因为虽然参数是引用的副本,但这个副本和原引用指向同一个对象实例,修改对象的成员变量本质是修改堆内存里的对象数据,所以原引用能看到这个变化。
2. 如何真正把原对象引用设为null?
要让方法能修改原引用本身(而不是引用指向的对象),你需要用ref关键字来传递参数——这相当于传递的是引用变量本身的地址,而不是引用的副本。
修改后的代码如下:
public class Sample{ public int c; } public class Program { public static void Main(string[] args) { Sample c = new Sample(); Console.WriteLine(c.c); // 输出0 f(c); Console.WriteLine(c.c); // 输出2 g(ref c); // 这里要判断c是否为null,不然直接访问c.c会抛出空引用异常 Console.WriteLine(c == null ? "null" : c.c.ToString()); // 输出null } static void f(Sample c){ c.c = 2; } static void g(ref Sample c){ c = null; } }
这样调用g(ref c)时,g方法里的c直接关联Main里的那个变量,赋值null就会真正改变原变量的指向。
补充说明
你提到预期最后输出null,要注意Sample类的c成员是int类型(值类型),它本身不能为null——你实际想实现的是让Sample类型的变量c变成null,这时候直接访问它的成员会抛出异常,所以上面的代码里加了空判断,直接输出"null"。
内容的提问来源于stack exchange,提问作者Mohsen Jafari
相关产品推荐
相关产品推荐

