从方法 C# 返回数组

Returning array from methods C#

我一直在想,为什么我的方法不是修改数组,当我将它用作参数并使它等于另一个具有不同值的数组时,在方法内部? 我只是在更改参考地址吗?

    static void Main()
    {
        string[] array = { "yes", "no", "maybe" };
        TestO(array); // Still "yes", "no", "maybe"
    }

    static void TestO(string[] array)
    {
        string[] secondArray = new string[array.Length]; 
        secondArray[0] = "1";
        secondArray[1] = "2";
        secondArray[2] = "3";
        array = secondArray; 
    }

我的猜测:我没有修改 Main() 中的数组,因为在 Test0() 方法中执行 array = secondArray; 时, 我只是把array的引用地址改成了secondArray.

如果我的猜测不对,我的问题是,为什么它没有被修改?

(我知道我可以将 Test0() 修改为 string[] return 方法和 return 修改后的 secondArray 并将其传递给arrayMain())

另外一个问题是: 如果我使用 string[] return 方法,并声明如下:

        static void Main()
    {
        string[] array = { "yes", "no", "maybe" };
        array = TestO(array); 
    }

    static string[] TestO(string[] methodArray)
    {
        string[] secondArray = new string[methodArray.Length];
        secondArray[0] = "1";
        secondArray[1] = "2";
        secondArray[2] = "3";
        return secondArray; 
    }

array = TestO(array); 我只是将 secondArray[] 的参考地址传递给 array[] 还是我只传递它的值? (应该是参考地址,但我想确定是否弄错了)

您不需要 return 任何东西,只需使用 ref

static void Test( ref string[] array)
    {
        string[] secondArray = new string[array.Length]; 
        secondArray[0] = "1";
        secondArray[1] = "2";
        secondArray[2] = "3";
        array = secondArray; 
    }

当您将数组传递给方法时

static void Test0(string[] array)
{

您正在向该数组传递一个 引用。该引用实际上是 immutable(您得到的是引用的副本,而不是原始引用),因此您不能更改参数引用并期望它影响外部代码测试方法。

虽然您可以这样做以获得您想要的行为:

static void Test0(ref string[] array)
{

它不被认为是好的 C# 风格。字符串本身是不可变的; “正确”的风格是 return 他们从方法。字符串数组也是如此。

使用此技术唯一可以节省的是额外的引用和 return 语句,因为无论如何您仍在创建新字符串和新数组。

I just changed the reference address of array to secondArray. If my guess is not right, my question is, why exactly is it not getting modified?

我认为你倾向于理解内存中有两个对一个数据的引用(没有两个数据);您有一个指向数据的变量 array。您调用一个方法,另一个方法,复制引用建立到相同的数据。您创建了一个新对象,然后将复制的引用指向新对象,将原始引用指向原始数据,然后您丢弃了复制引用和新数据。您又回到了完全相同的情况开始于。

逐行图示(我将您的方法参数重命名为 arrayX,所以区别很明显):

如果你用ref装饰参数并用ref调用它没有副本,所以被调用的方法可以修改原始引用并将它指向其他地方:

请注意,在这些情况的任一中,完全可以修改数组的内容。正在做:

arrayX[0] = "New data";

.. 将在 或者 情况下生效并且打印 array[0] 将显示“新数据”。修改箭头末端的数据时,起点是原始参考还是副本并不重要。这纯粹关于方法是否有权将传递给它的原始引用指向不同的对象

通常我们这样做。我们采用您的第二个代码块的样式 - return 数据。将其视为粗鲁可能会有所帮助 - 想象一下您的朋友说他会在您度假时照看您的植物;你把钥匙给了你的朋友。他把你的植物换成他更喜欢的另一种植物;你很不高兴,因为你有那株植物十年了..

很少有理由使用 ref 或相关的“覆盖您的引用的权力”- out。不要将它用于“我想从我的方法中 return 多个东西”——在面向对象的世界中,我们总是可以 return 一个东西代表两个数据项。我们不需要“return两件事”;我们可以 return 一件东西里面有两件东西...

//don't:
void GetPerson(ref string name, ref int age)

//consider a class:
Person GetPerson()
  return new Person(){ Name = ..., Age = ...}

//or a Tuple
(string Name, int Age) GetPerson

让调用方法选择是否应该覆盖它自己的变量,而不是让一些“第三方”把地毯从它脚下拉下来