1

I have an object which stores two strings and overrides the ToString() method to return one of those strings

            fooBar temp;
            foreach (string foo in bar)
            {
                temp = new fooBar(); <--- Why is this line needed when I 
                am overwriting the code and path on each cycle before adding?

                temp.code += ".";
                temp.path += ".";

                Console.WriteLine(temp);
                clbFooBar.Items.Add(temp);
            }

The prints to the console obey the overwritten code and path string values, but the checked list box items are all exactly the same thing (the last item's ToString()), what underlying process is going on that isn't immediately obvious?

If I change it to clbFooBar.Items.Add(temp.ToString()); it works absolutely fine, but wouldn't that be the same as temp.ToString.ToString() because .Add calls .ToString() in the first place? I figured both a console print and .Add would act the same seeing as they both call ToString()

EDIT: temp = new fooBar(); is the fix to my problem, I just want to know why this is the fix when intuition leads me to think that overwriting the two strings, code and path, should be enough and why without this re-initialisation, all of the items in the checked list box are the same.

6
  • Do you mean they are the same if you remove the line temp = new fooBar();? Commented Jul 6, 2016 at 13:47
  • No, the console print and checked list box only reflect each other if that line is present, which makes no sense to me. Commented Jul 6, 2016 at 13:50
  • I meant, the items in your checkedlistbox look all the same if this line is not present, but are (correctly) different if that line is present? Commented Jul 6, 2016 at 13:52
  • Exactly! Similarly, clbFooBar.Items.Add(temp.ToString()) works too, but I'm not sure if that still allows me access to the other string within the object. Commented Jul 6, 2016 at 13:54
  • 1
    Can you edit the question and add a simple code to reproduce the problem. Containing your classes. Currently (for me) it's unclear what you are asking. Commented Jul 6, 2016 at 13:56

2 Answers 2

3

So you're question seems to be why your code works correctly if you keep the line

temp = new fooBar();

in your loop, but does fill your CheckedListBox with all equal items if you ommit this line.

The reason is that if you create only one instance of fooBar outside the loop like that:

fooBar temp; = new fooBar();
foreach (string foo in bar)
{
    temp.code += ".";
    temp.path += ".";
    clbFooBar.Items.Add(temp);
}

then you are adding the same instance multiple times, and you change the properties of that instance in each iteration.

If you create new instances inside your loop like that:

foreach (string foo in bar)
{
    fooBar temp; = new fooBar();
    temp.code += ".";
    temp.path += ".";
    clbFooBar.Items.Add(temp);
}

you have a new instance for every iteration and don't change the already added instances.


Update: just noticed that they still will all look the same as you set them all to whatever default value code and temp have plus a ".". So it's still a little unclear what you actually try to do. maybe something like this:

string s = string.Empty;
foreach (string foo in bar)
{
    s += ".";
    fooBar temp; = new fooBar();
    temp.code = s;
    temp.path = s;
    clbFooBar.Items.Add(temp);
}
Sign up to request clarification or add additional context in comments.

6 Comments

Ah! So what you're saying is, the instances currently in the checked list box reflect the instance regardless, which is why they all appear to be the last item, as that's what the instance currently is after adding all the items. I made the assumption that checked list box items aren't a reference to the instance you pass it, but a copy of what you pass. Thanks!
@Bradley: I'm saying that if you only create one instance, than there is only that one instance. Yes, you inserted this same instance multiple times into your checkedlistbox and changed it's properties in each iteration. So the last change is what was displayed then in your checkedlistbox.
Thanks a lot, this one boggled the mind! Is it Friday yet?
What's the point of the foreach in this case? You're not using the variables in the loop. Why not just do a while loop with the count of bar?
Very good point. The code and path use foo in my code, I just didn't reflect that in my example and quickly just wanted to illustrate that code and path change on each pass, apologies.
|
0

You are creating temp outside the foreach loop, then initializing it inside.

If you don't reinitialize with each pass of the loop what you end up with is a CheckedListBox where all of the items within it point to the same object.

That's why you're getting the value of the last object (because there is actually only) when you look in the list.

I'm guessing that what you actually want to do is add each item (foo) in bar to the CheckedListBox. If so use this.

        foreach (string foo in bar)
        {
            foo.code += ".";
            foo.path += ".";

            Console.WriteLine(foo);
            clbFooBar.Items.Add(foo);
        }

7 Comments

I don't think I'm explaining myself very well, the complete opposite is happening. If I don't re-initialise on each pass, the result is that the whole checked list box contains what appears to be duplicates of the last item.
Yeah I understand. The problem is as I've described. Have you tried my approach?
Your approach was exactly my approach and is what gave me the issue in the first place. The re-initialisation fixes the problem, I just want to know why! Haha
Actually if you look at my approach I'm modifying the code and path properties of the foo variable, initialized in the foreach loop. Your code was using temp which is initialized outside the loop.
Ah yes, sorry I didn't read your code thoroughly. Temp is the object I need to add as it contains two strings which I both need, you're mistaking foo as the type I'm using, you cannot have sub-strings within strings! :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.