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

时间:2016-04-06 20:34:45

标签: c# list generics reference reference-type

我在以下代码中遇到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]);
            }
    }
}

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

2 个答案:

答案 0 :(得分:3)

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

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

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]);
        }
}

我会注意到我发现这不是正在阅读“你的”代码,而是通过调试它。策略性地设置断点和手表使这样的问题更容易解决。调试是理解代码中问题的宝贵技能,尤其是您没有编写的代码。

答案 1 :(得分:0)

您可以从 this 回答中学习,所有数组都是引用类型。

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

permutations.Add(list);

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

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

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

底线:

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

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

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