【问题标题】:Why can't I re-initialize an Array in a function?为什么我不能在函数中重新初始化数组?
【发布时间】:2017-01-07 04:42:37
【问题描述】:

在 C# 中,数组通过引用传递给函数,这意味着这段代码:

static void FillArray(int[] A) {
     for (int i = 0; i < A.Length; i++) {
          A[i] = -1;
     }
}

static void Main(string[] args) {
    int[] A = new int[10];

    FillArray(A);

    Console.WriteLine(string.Join(" ", A));
}

将产生-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 这是预期的答案。但是如果我像这样重新初始化数组:

static void FillArray(int[] A) {
    A = new int[2*A.Length];
    for (int i = 0; i < A.Length; i++) {
        A[i] = -1;
    }
}

输出将是0 0 0 0 0 0 0 0 0 0 !!

A 不应更改,因为它是作为对函数的引用传递的?

【问题讨论】:

  • A 是一个引用对象。但是您正在按值传递该引用对象。 @JonSkeet 对此有a good article
  • int[] 是引用类型,但A 不是通过引用传递的。它们是许多人混淆的两个不同的术语。术语“引用类型”是关于类型的。术语“按引用传递”是关于变量的。您可以通过将方法更改为FillArray(ref int[] A)来通过引用传递A
  • 是时候开始阅读一些 c# 文档了.....

标签: c# arrays pass-by-reference pass-by-value


【解决方案1】:

当 FillArray 开始运行时,它有一个名为 A 的变量,它指向您在 main 中设置的数组(恰好称为 A)

在第二种情况下,您将本地 A 更改为指向不同的数组。因此,调用代码看不到您所做的任何更改 - 2 A 变量之间没有关系

实际上这不是“通过引用”参数传递,因为更改传递的值 (A) 不会反映在调用者空间中。您正在按值获取“指针”(在引号中,因为 c# 会争辩它不是指针,因为托管代码没有指针)

【讨论】:

    【解决方案2】:

    在内部,数组的地址就是正在传递的内容。通过修改该数组中的项目,调用者将看到这些更改。但是如果将数组分配给一个新数组,它就不再指向调用者的数组。调用者不会看到该数组有任何变化。

    因此,虽然数组是按引用传递的,但引用本身是按值传递的,除非您使用 ref 关键字。

    【讨论】:

      【解决方案3】:

      您可以更改数组A 中包含的值,但不能更改A。当您调用一个方法时,您实际上传递了参数值的副本(默认情况下)。如果你想改变A,你必须通过引用传递它,使用ref关键字:

      static void FillArray(ref int[] A) {
          A = new int[2*A.Length];
          for (int i = 0; i < A.Length; i++) {
              A[i] = -1;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-01-07
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        • 2021-08-18
        • 1970-01-01
        • 2015-02-09
        • 1970-01-01
        相关资源
        最近更新 更多