开发者

C# List Manipulation - Output Different When Stepping Through vs. Running

I'm a C# newbie and I'm really confused about something I'm trying to do for a project in a C# class.

The assignment is some list manipulation in C#.

The program accepts a list of items in the text box, then iterates through those items, creating multiple copies of the list. It randomly resizes each copy of the list to between 3 and all items. It then outputs all the copies.

The problem I'm having is that when I step through this program with the debugger, I get the expected output. The same happens if I display a message box after each iteration (as I have in the code below).

However, if I just run the program straight through, I get a different output. Instead of variations in the lists, all the copies of the list are exactly the same.

If you see in the code I've commented "// FIRST DEBUG MESSAGEBOX" and "// SECOND DEBUG MESSAGEBOX". If the first debug messagebox code is left in there, the output is as expected...multiple versions of the list are output with random lengths between 3 and all items.

However, and this is where I'm confused...if you comment out the first debug messagebox code, you get a different result. All versions of the list output are the same length with no variation.

Any help would be appreciated! Here's the code I have so far...sorry if it's terrible - I'm new at 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 ma开发者_Go百科x 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);
    }
}


Move the creation of Random out of the loop:

Random random = new Random();

By default, the constructor uses a default time based seed. In a tight loop, you may be getting 'the same' random generator instead of a different one with each loop.

When using MessageBoxes or single stepping, you are allowing the timer to run and getting 'a new' random generator in each loop.


I don't understand your assignment exactly, but this loop seems to be incorrect:

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

when you remove an element in the middle of a list, elements after that get shifted, so not all the elements after maxIndex get removed, as you might expect.


In circumstances where stepping through the code in a debugger affects the behaviour of the program, a useful alternative debugging technique is to use the System.Diagnostics namespace in particular the Trace class.

The Trace functions work much like Console.WriteLine(), you can trace a string or a format string plus an array of objects to populate the format string, e.g.:

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

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜