离开方法时从列表中丢失值

Losing values from list when leaving method

我在使用以下代码中的 2 个列表时遇到问题:

internal class Program
{
    private static readonly List<char[]> permutations = new List<char[]>();

    private static void Main()
    {
        string str = "0123456789";
        char[] arr = str.ToCharArray();
        GetPer(arr);
        //2. here we have lost all the values
        Console.ReadKey();
    }

    private static void Swap(ref char a, ref char b)
    {
        if (a == b) return;
        a ^= b;
        b ^= a;
        a ^= b;
    }

    public static void GetPer(char[] list)
    {
        int x = list.Length - 1;
        GetPer(list, 0, x);
    }

    private static void GetPer(char[] list, int k, int m)
    {
        if (k == m)
        {
            permutations.Add(list); //1. here we add value to the list
        }
        else
            for (int i = k; i <= m; i++)
            {
                Swap(ref list[k], ref list[i]);
                GetPer(list, k + 1, m);
                Swap(ref list[k], ref list[i]);
            }
    }
}

有 2 条评论,第一个在 void GetPer 中,我们将值添加到列表中。第二条评论在 void Main 中,我们丢失了所有以前的值。如果需要任何解释,代码主要是从此处复制粘贴的 Listing all permutations of a string/integer。我怎样才能避免这个引用类型问题?

您一遍又一遍地添加对同一个列表的引用。您复制的方法交换两个值,递归 运行s 另一个排列,然后将它们交换回来。最终,在您 运行 完成所有排列后,列表又回到了它开始的位置。

原始程序只是将排列写入控制台,因此在每次排列后展开更改并不重要。如果在将列表添加到结果时复制列表,您应该会看到所有排列:

private static void GetPer(char[] list, int k, int m)
{
    if (k == m)
    {
        permutations.Add((char[])(list.Clone())); //1. here we add a clone of the value to the list
    }
    else
        for (int i = k; i <= m; i++)
        {
            Swap(ref list[k], ref list[i]);
            GetPer(list, k + 1, m);
            Swap(ref list[k], ref list[i]);
        }
}

我会注意到我发现这不是阅读"your"代码,而是调试它。有策略地放置断点和监视可以使此类问题更容易解决。调试是理解代码中问题的宝贵技能,尤其是您未编写的代码。

你可以从this的回答中了解到,所有数组都是引用类型。

这意味着,当您在这行代码中将数组添加到数组列表时:

permutations.Add(list);

您实际上是在一遍又一遍地添加相同的数组。由于每次来回交换该数组中的值,您都会获得对同一数组的引用列表。

如果我没理解错的话,您想在您创建的第一个数组中列出所有可能的字符顺序。

为此,您需要克隆您的数组,而不是使用相同的引用。


底线:

您应该将添加到 collection 行更改为:

permutations.Add((char[])list.Clone());

这样,您添加的不是相同的引用,而是它的克隆,您的最终列表将充满不同的数组。