按值、按引用和作为输出变量传递数组参数

时间:2022-11-19 21:30:58

在C#中,类是引用类型的数据类型,而数组在C#中被定义类类型,所以数组也是引用类型。当把一个数组变量传递给一个方法时,方法有可能会改变我们引用的数组的内容——即使是按值传递。但这并不意味着因为数组是引用类型,按值传递就和按引用传递的结果一样。

示例:

  static void Main()
  {
   String[] names;
   names = new String[] { "Mark", "Scott", "Maria", "Diana" };
   PassByValues(names);
   Console.WriteLine(names[0]);
   names = new String[] { "Mark", "Scott", "Maria", "Diana" };
   PassByReference(ref names);
   Console.WriteLine(names[0]);
   names = new String[] { "Mark", "Scott", "Maria", "Diana" };
   PassAsOutput(out names);
   Console.WriteLine(names[0]);
  }

  public static void PassByValues(string[] n)
  {
   n[0] = "Breff";
   n = new string[] {"Julie", "Fiona", "Jack"};
  }

  public static void PassByReference(ref string[] n)
  {
   n[0] = "Breff";
   n = new string[] {"Julie", "Fiona", "Jack"};
  }

  public static void PassAsOutput(out string[] n)
  {
   // n[0] = "Breff"; // can't access an output parameter before it is assigned
   n = new string[]{"Julie", "Fiona", "Jack"};
  }

先说第二和第三个方法,在第二个方法里,参数按引用传递,用一个新的数组代替了原来了数组,所以其输出值为Julie。在第三个方法里,变量作为输出变量传递,行为上像按引用传递,但在方法中访问输出参数的一个未赋值的元素会造成编译错误(这里有点奇怪,明明传递进去的是已经赋过值的names,怎么会未赋值呢?)。

第一个方法的输出有点奇怪,输出值并不是Julie,也不是Mark,而是Breff。造成这个现象的原因"引用"与"引用类型"的区别。数组虽然是引用类型,在按值传递时,并不会完全等同于按引用传递。按值传递时,由于数组是引用类型,形参n将和实参names引用同一块内存,即数组{ "Mark", "Scott", "Maria", "Diana" },所以方法里第一句语句改变了该数组的第一个元素。但接下来 n = new string[] {"Julie", "Fiona", "Jack"};一句却使形参n引用一块新申请的内存,此时它已经与实参names脱离了联系。所以输出的是Breff,而不是n新申请内存后的Julie。

总结一下,数组作为参数在按值传递时,由于数组本身是引用类型,所以形参在方法被调用时将和实参引用同一块内存,但当使用new语句时,会将形参引用到其它地方,与实参脱离关系;在按引用传递时,形参和实参自始至终引用同一块内存;以输出变量的形式传递时,形参初始化时是一个空引用,要在方法里为其申请内存,在方法返回时将才将实参引用到形参引用的内存从而实现输出功能。