C# 中 方法调时的参数若是一个对象,使用 in 与 ref 或完全不用 in/ref 的区别

in/ref 不用的话,传入的是对象的引用值。如:Call( Class c )。在方法中若将此参数变量赋值为null,并不会影响到传入前外部的实例引用。也就是说,在方法中这个变量是一个局部引用变量。

类似于 C/C++ 中,传入一个对象或 结构 的指针地址。在方法里把这个地址改成0后,方法外保存实例的变量值并不会被修改。

void changeTest(testClass c)
{
     c.i = 900;
     c = null;  
}

...

void foo()
{
    testClass t = new testClass();
    
    changeTest(t);

    Console.WriteLine("{0}", t.i ); //这里输出900, t值并不为null,还是有效的
}

 

用 in 的话,与上面一种情况一样,传入的是对象的引用值。但编译器为了合理化 in 的意思,会在编译时进行检查,让这个引用变量值在此方法内不能被修改。

void changeTestIn(in c)
{
    c.i = 300;
    
    c = new testClass(); //在编译时,这里出会现问题,编译不过
}

  

用 ref 的话,必须引用到一个实体变量,无论这个变量是存贮什么。编译器为了合理化 ref 的意思,会在编译时进行检查,若传入 一个 null 值,它只是一个关键字,不存一个实体变量的地址,说明不可能被 ref,编译时就会报错。但若 可以引用到某个实体变量,就算变量的值为 null,也是可以编译通过的。因为存在一个实体变量可以被 ref。

传入后方法内部可以把这个变量值改为 null,就等于把这个实体变量的值 为null了,此时这个变量就不再指向原来那个实体了。那个实体若在程序中没有其它变量再指向它,因为被引用为0次,不久后可能就会被自动GC。

void changeTestRefNULL(ref testClass c)
{
  if( null != c)
    c.i = 300;
}

void changeTestRef(ref testClass c)
{
   c.i = 200;
}

void changeTestRefToNULL(ref testClass c)
{
   c.i = 1000;
   c = null; //可以的
}

void test()
{
  testClass t = null;
  changeTestRefNULL(ref t); //ok
  changeTestRefNULL(ref null); //在编译时,这里会出问题,编译不过
  t = new testClass();
  changeTestRef(ref t);
  Console.WriteLine("after changeTestRef(), i = {0}", t.i); // 输出 after changeTestRef(), i = 200
  changeTestRefToNULL(ref t);
  Console.WriteLine("after changeTestRefToNULL(), i = {0}", t.i); //运行时出错,因为 t 此时为 null
}
posted @ 2025-01-28 14:56  PencilStart  阅读(23)  评论(0)    收藏  举报