C#列表操作 - 步进与运行时输出不同

时间:2011-03-12 23:14:06

标签: c#

我是C#新手,我真的很困惑我正在尝试为C#课程中的项目做些什么。

赋值是C#中的一些列表操作。

程序接受文本框中的项目列表,然后遍历这些项目,创建列表的多个副本。它随机地将列表的每个副本调整为3到所有项目。然后输出所有副本。

我遇到的问题是,当我使用调试器逐步执行此程序时,我得到了预期的输出。如果我在每次迭代后显示一个消息框(正如我在下面的代码中所示),也会发生同样的情况。

但是,如果我直接运行程序,我会得到不同的输出。而不是列表中的变化,列表的所有副本都完全相同。

如果你在代码中看到我评论了“// FIRST DEBUG MESSAGEBOX”和“// SECOND DEBUG MESSAGEBOX”。如果第一个调试消息框代码留在那里,输出就像预期的那样...输出列表的多个版本,随机长度介于3和所有项目之间。

然而,这就是我感到困惑的地方......如果你注释掉第一个调试消息框代码,你会得到不同的结果。列表输出的所有版本都是相同的长度,没有变化。

任何帮助将不胜感激!这是我到目前为止的代码...对不起,如果它很可怕 - 我是C#的新手:

public partial class MainForm : Form
{
    /**
     * Vars to hold raw text list items
     * and list items split by line
     */
    String rawListItems = "";
    List<string> listItems = new List<string>();
    List<List<string>> textListItems = new List<List<string>>();

    public MainForm()
    {
        InitializeComponent();
    }

    private void cmdGo_Click(object sender, EventArgs e)
    {
        // store the contents of the list item text box
        this.rawListItems = txtListItems.Text;
        this.listItems.AddRange(Regex.Split(this.rawListItems, "\r\n"));

        // setup min and max items - max items all items
        int minItems = 3;
        int maxItems = this.listItems.Count;

        // We'll copy this list X times, X = same number of items in list
        for (int i = 0; i < this.listItems.Count; i++)
        {
            // make a copy of the list items
            List<string> listItemsCopy = new List<string>(this.listItems);

            // get a random number between min items and max items
            Random random = new Random();
            int maxIndex = random.Next(minItems, maxItems + 1);    // max is exclusive, hence the +1

            // remove all elements after the maxIndex
            for (int j = 0; j < listItemsCopy.Count; j++)
            {
                if (j > maxIndex)
                {
                    listItemsCopy.RemoveAt(j);
                }
            }

            // add the list copy to the master list
            this.textListItems.Add(listItemsCopy);

            // FIRST DEBUG MESSAGEBOX
            String tst = "";
            foreach (string item in listItemsCopy)
            {
                tst += item + " ## ";
            }
            MessageBox.Show(tst);
        }

        // SECOND DEBUG MESSAGEBOX
        String output = "";
        foreach (List<string> listitem in this.textListItems)
        {
            foreach (string item in listitem)
            {
                output += item + " ## ";
            }
        }
        MessageBox.Show(output);
    }
}

3 个答案:

答案 0 :(得分:2)

将Random的创建移出循环:

Random random = new Random();

默认情况下,构造函数使用基于默认时间的种子。在一个紧密的循环中,你可能会得到“相同的”随机生成器而不是每个循环的不同生成器。

使用MessageBoxes或单步执行时,您允许计时器在每个循环中运行并获取“新的”随机生成器。

答案 1 :(得分:0)

我完全不明白你的作业,但这个循环似乎不正确:

   for (int j = 0; j < listItemsCopy.Count; j++)
   {
       if (j > maxIndex)
       {
           listItemsCopy.RemoveAt(j);
       }
   }

当你删除列表中间的元素时,之后的元素会被移位,所以maxIndex之后的所有元素都不会被删除,正如您所期望的那样。

答案 2 :(得分:0)

在调试器中逐步执行代码会影响程序行为的情况下,一种有用的替代调试技术是使用System.Diagnostics命名空间,特别是Trace类。

Trace函数的工作原理与Console.WriteLine()非常相似,您可以跟踪字符串或格式字符串以及对象数组以填充格式字符串,例如:

Trace.TraceInformation("some message that tells me something");

Trace.TraceInformation("some useful format string {1}, {0}", 
    new object[] {someObject, someOtherObject});