【问题标题】:Passing array then use OrderBy vs Sort - changing original array [duplicate]传递数组然后使用 OrderBy vs Sort - 改变原始数组[重复]
【发布时间】:2018-01-13 17:19:36
【问题描述】:

为什么ArrayCalledWithOrderBy 不会改变原来传递的数组,而ArrayCalledWithSort 会?

编辑:至于建议重复的链接。一个链接中甚至没有 OrderBy,因此它显然不是重复的。另一个链接实际上是询问 OrderBy 和 Sort 之间哪个更好,而不是为什么不更改原始数组。

public static void ArrayCaller()
{
   var arr = new string[] { "pink", "blue", "red", "black", "aqua" };
   DisplayArray(arr, "Before method calls");

   ArrayCalledWithOrderBy(arr);
   DisplayArray(arr, "After method call using orderby");

   ArrayCalledWithSort(arr);
   DisplayArray(arr, "After method call using sort");
}

public static void ArrayCalledWithOrderBy(string[] arr)
{
    // this does not change the original array in the calling method. Why not?
    arr = (arr.OrderBy(i => i).ToArray()); 
    DisplayArray(arr, "After orderby inside method");
}

public static void ArrayCalledWithSort(string[] arr)
{
    // this changes the original array in the calling method. 
    // Because it is using the same reference? 
    // So the above code for orderby does not?
    Array.Sort(arr);
    DisplayArray(arr, "After sort inside method");
}

public static void DisplayArray(string[] arr, string msg)
{
    for (int i=0; i<arr.Length; i++)
    {
        Console.Write($"{arr[i]} ");
    }
    Console.WriteLine($" - {msg}");
} 

// OUTPUT
//pink blue red black aqua  - Before method calls
//aqua black blue pink red  - After orderby inside method
//pink blue red black aqua  - After method call using orderby
//aqua black blue pink red  - After sort inside method
//aqua black blue pink red  - After method call using sort

【问题讨论】:

  • @NisargShah 不。这个问题询问为什么ArrayCalledWithOrderBy 中的覆盖arr 数组不会更新ArrayCaller() 中的arr 数组。 This question 是关于字符串的传递,但可以很容易地更改为数组。
  • @NisargShah。看起来链接正在尝试确定哪个是更好的选择。我试图确定为什么一个改变了原始数组而另一个没有。
  • @NisargShah 首先不是重复的。很明显,OP 询问为什么更改 arr 没有反映在 ArrayCaller()
  • @ColeJohnson 我不介意 Niki 同意你的看法。但从最初的措辞来看,这似乎是一个明显的重复。
  • 从您的声明arr = (arr.OrderBy(i =&gt; i).ToArray());,我推断您确实了解OrderBy() 不会修改数组。如果不这样做,请参阅第二个标记的重复项。您似乎理解的是,默认情况下,方法参数是按值传递的,对这些参数值的更改不会影响调用者的变量(如果有的话)。您需要使用refout 来修改调用者的变量。有关详细信息,请参阅第一个标记的副本,包括它如何应用于您的确切情况(即使用数组)。

标签: c# arrays


【解决方案1】:

数组是引用类型,因此当您将数组传递给方法时。它的reference是由value传递的。

您应该知道此方法中的arr

public static void ArrayCalledWithOrderBy(string[] arr)
{
    arr = (arr.OrderBy(i => i).ToArray()); 
    DisplayArray(arr, "After orderby inside method");
}

这里是arr

var arr = new string[] { "pink", "blue", "red", "black", "aqua" }; DisplayArray(arr, "方法调用前");

ArrayCalledWithOrderBy(arr);

是两个不同的变量持有对同一个数组的引用,直到这一行:

arr = (arr.OrderBy(i => i).ToArray()); 

在这一行中,您将arr 更改为引用排序后的数组,而不是传入的数组。看到了吗? OrderBy 创建一个已排序的新数组。原始数组没有发生变异。

Array.Sort 改变传入的数组,所以它实际上改变了这里的arr

var arr = new string[] { "pink", "blue", "red", "black", "aqua" };

【讨论】:

  • 感谢您的详细解释。您的回答和 ColeJohnson 的回答清楚地说明了我现在数组发生了什么。
【解决方案2】:

在这一行:

arr = (arr.OrderBy(i => i).ToArray()); 

您正在创建一个新数组并分配给arr。您传递给该函数的数组不再可由该函数访问。如果你希望能够修改数组arr以便其他函数可以使用它,你需要使用ref keyword

public static void ArrayCalledWithOrderBy(ref string[] arr)

【讨论】:

    【解决方案3】:

    调用 arr.OrderBy(i => i).ToArray() 后,您可以使用 Object.ReferenceEquals 检查 arr 的引用是否发生变化。

    public static void ArrayCalledWithOrderBy(string[] origin)
       {
           var arr = (origin.OrderBy(i => i).ToArray());
           //isEqual flag is false
           var isEqual = Object.ReferenceEquals(arr, origin);
    
          DisplayArray(arr, "After orderby inside method");
       }
    

    【讨论】:

    • 这是一个很好的提示!我也会这样做。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 2020-05-22
    • 2020-10-08
    • 1970-01-01
    相关资源
    最近更新 更多