【问题标题】:C# - strange behaviour with ToList() and ToArray()C# - ToList() 和 ToArray() 的奇怪行为
【发布时间】:2016-10-21 12:00:44
【问题描述】:

我注意到在 C# 中结合使用 ToList() 和 ToArray() 时出现了一些奇怪的行为(使用 .NET 4.5.2 框架)。

给定以下测试程序:

int[] array = { 5, 1, -10, 667, 4 };
SorteerBib<int>.SelectionSort(array, Comparer<int>.Default);
Console.Out.WriteLine("Result - WRONG!");
for (int i = 0; i < array.Length; i++)
{
    Console.Out.Write(array[i] + " ");
    Console.Out.WriteLine();
}
Console.ReadKey();

SorteerBib 类包含 2 个方法:

class SorteerBib<T>
{
    public static IList<T> SelectionSort(IList<T> list, IComparer<T> comparer)
    {
        for (int i = 0; i < list.Count - 1; i++)
        {
            int minIndex = i;
            for (int j = i + 1; j < list.Count; j++)
            {
                if (comparer.Compare(list[j], list[minIndex]) < 0)
                {
                    minIndex = j;
                }
            }
            T temp = list[i];
            list[i] = list[minIndex];
            list[minIndex] = temp;
        }

        Console.Out.WriteLine("Result SelectionSort IList - OK");
        for (int i = 0; i < list.Count; i++)
        {
            Console.Out.Write(list[i]+" ");
            Console.Out.WriteLine();
        }
        return list;
    }

    public static void SelectionSort(T[] array, IComparer<T> comparer)
    {
        // DOES NOT WORK, WHY?
        array = ((SelectionSort(array.ToList(), comparer)).ToArray());

        Console.Out.WriteLine("Result SelectionSort Array - OK");
        for (int i = 0; i < array.Length; i++)
        {
            Console.Out.Write(array[i] + " ");
            Console.Out.WriteLine();
        }
    }
}

错误在于第二种方法的第一行:

array = ((SelectionSort(array.ToList(), comparer)).ToArray());

在 void 方法中,数组在这一行之后排序,但是一旦我们返回主程序,排序就消失了。

将这一行替换为以下几行可以解决此问题:

IList<T> temp = SelectionSort(array.ToList<T>(), comparer);
for (int i = 0; i < array.Length; i++) {
    array[i] = temp[i];
}

谁能解释这种不可预测的行为? 非常感谢!

【问题讨论】:

  • 没有不可预知的行为,将数组作为 byref 传递,然后它将起作用,第二种方法起作用,因为您要替换数组中的元素,而不是数组本身。
  • 仅供参考,数组实现IList&lt;T&gt;,因此在将数组传递给第一个数组时不需要第二种方法或调用ToList
  • 同意@Gusman,this 解释了原因。

标签: c# linq


【解决方案1】:

您正在传递不带 ref 关键字的数组,然后通过执行以下操作更改它的引用:

array = ((SelectionSort(array.ToList(), comparer)).ToArray());

由于未使用ref 关键字,因此更改仅适用于函数。

解决方法是添加 ref 关键字:

public static void SelectionSort(ref T[] array, IComparer<T> comparer)

顺便说一句,更好的方法是对ICollection&lt;T&gt;IEnumerable&lt;T&gt; 进行排序。

【讨论】:

  • IEnumerable&lt;T&gt; 进行排序会更好地返回它,而不是更改传入的引用。
  • @juharr - 我知道,但我认为将数组转换为列表更好,反之亦然。
  • 实际上不需要转换数组,因为它实现了IList&lt;int&gt;
  • @juharr - 这也是一种选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多