【问题标题】:C# List Manipulation - Output Different When Stepping Through vs. RunningC# 列表操作 - 单步执行与运行时输出不同
【发布时间】:2011-03-13 07:39:54
【问题描述】:

我是一个 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);
    }
}

【问题讨论】:

    标签: c#


    【解决方案1】:

    将 Random 的创建移出循环:

    Random random = new Random();
    

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

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

    【讨论】:

    • 如此简单。做到了。谢谢您的帮助!我已经解决这个问题 2 天了!
    • @John - 学习一门新语言很糟糕。祝你好运!
    【解决方案2】:

    我不完全理解你的任务,但这个循环似乎不正确:

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

    当您删除列表中间的一个元素时,之后的元素会被移动,因此并非所有maxIndex 之后的元素都被删除,正如您所期望的那样。

    【讨论】:

    • 从 Steve Wellens 那里得到了很好的答案,解决了这个问题,但这是一个很好的提示。谢谢,我会努力解决这个问题。我会代表你,但我太新了,他们不会让我。
    【解决方案3】:

    在调试器中单步执行代码会影响程序行为的情况下,一种有用的替代调试技术是使用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});
    

    【讨论】:

      猜你喜欢
      • 2013-08-27
      • 1970-01-01
      • 2019-05-27
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多