C# foreach循环中的奇怪行为

7
在一整天的故障排除后,我已经将问题压缩到了这段微小的代码中。有人能解释一下为什么它不起作用吗?当消息框出现时,我期望[markets]为0 2 4 6,[city] [county]和[streets]为0 1 2 3。
        private void pieceoftestcode()
        {
            string[] county = new string[4];
            string[] city = new string[4];
            string[] markets = new string[4];
            string[] streets = new string[4];
            string[] items = new string[4] { "apple", "banana", "pineapple", "juice" };
            string[] value = new string[4];
            foreach (string item in items)
            {
                for (int i = 0; i <= 3; i++)
                {
                    if (item == "apple")
                        value[i] = (2 * i).ToString();
                    else
                        value[i] = i.ToString();
                }

                if (item == "apple")
                    markets = value;
                else if (item == "banana")
                    streets = value;
                else if (item == "pineapple")
                    county = value;
                else
                    city = value;
            }
            MessageBox.Show("test");
        }

我正在使用foreach循环遍历项目。如果该项目是“apple”,那么我期望[value]为0 2 4 6。最初[markets]被分配为0 2 4 6。但是,如果我逐步执行代码,似乎第二次执行foreach循环时,[markets]被覆盖了。为什么会这样?我做错了什么?一旦banana已经命中,[markets]不应再被分配值吧?


6
您只在整个过程中使用了一个名为value的数组,您不断覆盖它,并逐渐将其他变量的引用分配给这个相同的数组。 - Damien_The_Unbeliever
3
支持发布 [MCVE] 的点赞 - aloisdg
1
然而,如果我逐步执行代码,似乎第二次执行foreach循环时,[markets]被覆盖了。这是因为markets = value将两个引用设置为同一个数组 - 由于您正在为values数组分配不同的值,自然可以看到这些更改反映在使用数组的任何引用上。 - Zohar Peled
2个回答

3
你最终会发现所有的变量都引用同一个数组 value,并且该数组中的值是由最后一次迭代写入的。
有一种非常类似的编写代码的方式可以避免这个问题。
    private void pieceoftestcode()
    {
        string[] county = new string[4];
        string[] city = new string[4];
        string[] markets = new string[4];
        string[] streets = new string[4];
        string[] items = new string[4] { "apple", "banana", "pineapple", "juice" };
        string[] value;
        foreach (string item in items)
        {
            if (item == "apple")
                value = markets;
            else if (item == "banana")
                value = streets;
            else if (item == "pineapple")
                value = county;
            else
                value = city;
            for (int i = 0; i <= 3; i++)
            {
                if (item == "apple")
                    value[i] = (2 * i).ToString();
                else
                    value[i] = i.ToString();
            }


        }
        MessageBox.Show("test");
    }

现在,每次循环value被分配一个对不同数组的引用1,因此for循环不会覆盖之前的操作。


1假设items中不包含任何重复项,也没有多于一个非苹果、香蕉或菠萝的物品。


我现在明白了,我们正在创建两个数组之间的链接,而不是将一个数组中的值复制到另一个数组中。虽然我觉得有点奇怪,但我理解可能涉及到内存方面的好处。 - Maarten
@Maarten - 这不是两个数组之间的链接。你需要明确变量(比如markets)和该变量当前引用的数组之间的区别。在赋值中我们所做的就是改变特定变量正在引用的哪个数组。 - Damien_The_Unbeliever

0
你的主要问题在于代码中的这一部分。
            if (item == "apple")
                markets = value;
            else if (item == "banana")
                streets = value;
            else if (item == "pineapple")
                county = value;
            else
                city = value;

在语句中,你并没有创建一个新的数组 - 你只是将引用分配给对象。然后你在for()循环中改变了数组。


解决方案是创建数组的深层副本或复制值。 主要问题是“我在这里做错了什么”,而不是寻找解决方案。 - Fuffelschmerz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接