locked
class list strange behaviour RRS feed

  • Question

  • I have a timer class that looks like this:

    public class Timer
    {
        public bool Active;
        public DateTime Time;  
    }


    And a list of this class:

    public static List<Timer> timerList = new List<Timer>();

    In my constructor I populate the list with 5 timers, and set the Time element to DateTime.Now, and this works. Howerver, when I modify one of the list timers, it seems to effect them all, example:

    timerList[2].Time = DateTime.Now.AddSeconds(185);

    After this, all of the items int he list have changed their Time element, is this normal? It's not the effect I want.

    Tuesday, February 21, 2012 6:37 PM

Answers

  • Not really a mystery. In your first example, var something = "this"; calls the string constructoe with value "this" and assigns the address where "this" is stored to something. That address gets added to list. The line something = "That"; calls the string constructor and assigns the address where "That" is stored to something. That address gets added to the list. So the list contains two addresses - one for "this", one for "That".

    The same applies to the button example, mutatis mutandis.


    Regards David R
    ---------------------------------------------------------------
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    • Marked as answer by Bob Shen Monday, March 5, 2012 2:23 AM
    Tuesday, February 21, 2012 7:40 PM
  • ahhh the old by reference, by value trap...

    I've never totally figured out all variations of when it works and when it doesn't...

    For example is I say:

    var something = "this";
    list.add(something);
    something = "That";
    list.add(something);
    //ect.

    You will get "this" and "that" in the list!

    So this would be passing by value and not reference.  The question is how does one know ahead of time which is which?

    1. You create a string ("this") and point 'something' to "this".
    2. You add a copy of that pointer to the list; here the reference is passed by value.
    3. You alter 'something' to point to an entirely new string ("That").  Note that this is not modifying the underlying string, it is simply making a brand new one and changing the reference ('something') to point to that new value.
    4. You add a copy of that (new and different) pointer to the list; here the reference is passed by value.
    Button a = new Button("Press Me");
    control.add(a);
    a = new Button("Cancel");
    control.add(a);
    
    //this too is by value but the button name itself is the same.
    This is exactly the same as the previous example, except with Buttons, not strings.

    The example above indicates that the button named a is NOT a POINTER to the button object. Or is it?

    It is.
    Actually it is a pointer to the object, but the object was changed?
    The object was never changed; the pointer was changed to point to a new object.
    Then how does the control have two different objects, the only answer can be that when adding the control, a copy of it was made (by value)....
    No. Every time you use 'new' you make a new object. Those two times are the only times new objects were created, every other assigment is merely a copy of a reference and doesn't create a new Button.

    Other objects however, like a Dataset are ALWAYS by pointer (by reference). 

    Everything you have mentioned so far, in addition to the case brought up by the OP, is all discussing references. There are value types that act differently, and those are when you define a 'struct' rather than a 'class'.
    • Proposed as answer by Woohoooo Tuesday, February 21, 2012 8:25 PM
    • Edited by servy42 Tuesday, February 21, 2012 9:06 PM
    • Marked as answer by Bob Shen Monday, March 5, 2012 2:23 AM
    Tuesday, February 21, 2012 8:21 PM
  • ahhh the old by reference, by value trap...

    I've never totally figured out all variations of when it works and when it doesn't...

    For example is I say:

    var something = "this";
    list.add(something);
    something = "That";
    list.add(something);
    //ect.

    You will get "this" and "that" in the list!

    So this would be passing by value and not reference.  The question is how does one know ahead of time which is which?

    Button a = new Button("Press Me");
    control.add(a);
    a = new Button("Cancel");
    control.add(a);
    
    //this too is by value but the button name itself is the same.

    The example above indicates that the button named a is NOT a POINTER to the button object. Or is it? Actually it is a pointer to the object, but the object was changed? Then how does the control have two different objects, the only answer can be that when adding the control, a copy of it was made (by value)....

    Other objects however, like a Dataset are ALWAYS by pointer (by reference). 

    It's fun trying to figure it all out because most of the time it does exactly what I want rather than what it wants to do...


    JP Cowboy Coders Unite!

    • Marked as answer by Bob Shen Monday, March 5, 2012 2:23 AM
    Tuesday, February 21, 2012 7:08 PM

All replies

  • I figured it out, and I learned something new :D

    Basically when declaring the list and populating it, I created 1 instance of the timer class, and used that for every element in the list array thinking that it would be it's own instance, so what I did was declared a new timer for each array element and it fixed it.


    • Edited by Dodger666 Tuesday, February 21, 2012 6:57 PM
    Tuesday, February 21, 2012 6:57 PM
  • ahhh the old by reference, by value trap...

    I've never totally figured out all variations of when it works and when it doesn't...

    For example is I say:

    var something = "this";
    list.add(something);
    something = "That";
    list.add(something);
    //ect.

    You will get "this" and "that" in the list!

    So this would be passing by value and not reference.  The question is how does one know ahead of time which is which?

    Button a = new Button("Press Me");
    control.add(a);
    a = new Button("Cancel");
    control.add(a);
    
    //this too is by value but the button name itself is the same.

    The example above indicates that the button named a is NOT a POINTER to the button object. Or is it? Actually it is a pointer to the object, but the object was changed? Then how does the control have two different objects, the only answer can be that when adding the control, a copy of it was made (by value)....

    Other objects however, like a Dataset are ALWAYS by pointer (by reference). 

    It's fun trying to figure it all out because most of the time it does exactly what I want rather than what it wants to do...


    JP Cowboy Coders Unite!

    • Marked as answer by Bob Shen Monday, March 5, 2012 2:23 AM
    Tuesday, February 21, 2012 7:08 PM
  • Not really a mystery. In your first example, var something = "this"; calls the string constructoe with value "this" and assigns the address where "this" is stored to something. That address gets added to list. The line something = "That"; calls the string constructor and assigns the address where "That" is stored to something. That address gets added to the list. So the list contains two addresses - one for "this", one for "That".

    The same applies to the button example, mutatis mutandis.


    Regards David R
    ---------------------------------------------------------------
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    • Marked as answer by Bob Shen Monday, March 5, 2012 2:23 AM
    Tuesday, February 21, 2012 7:40 PM
  • ahhh the old by reference, by value trap...

    I've never totally figured out all variations of when it works and when it doesn't...

    For example is I say:

    var something = "this";
    list.add(something);
    something = "That";
    list.add(something);
    //ect.

    You will get "this" and "that" in the list!

    So this would be passing by value and not reference.  The question is how does one know ahead of time which is which?

    1. You create a string ("this") and point 'something' to "this".
    2. You add a copy of that pointer to the list; here the reference is passed by value.
    3. You alter 'something' to point to an entirely new string ("That").  Note that this is not modifying the underlying string, it is simply making a brand new one and changing the reference ('something') to point to that new value.
    4. You add a copy of that (new and different) pointer to the list; here the reference is passed by value.
    Button a = new Button("Press Me");
    control.add(a);
    a = new Button("Cancel");
    control.add(a);
    
    //this too is by value but the button name itself is the same.
    This is exactly the same as the previous example, except with Buttons, not strings.

    The example above indicates that the button named a is NOT a POINTER to the button object. Or is it?

    It is.
    Actually it is a pointer to the object, but the object was changed?
    The object was never changed; the pointer was changed to point to a new object.
    Then how does the control have two different objects, the only answer can be that when adding the control, a copy of it was made (by value)....
    No. Every time you use 'new' you make a new object. Those two times are the only times new objects were created, every other assigment is merely a copy of a reference and doesn't create a new Button.

    Other objects however, like a Dataset are ALWAYS by pointer (by reference). 

    Everything you have mentioned so far, in addition to the case brought up by the OP, is all discussing references. There are value types that act differently, and those are when you define a 'struct' rather than a 'class'.
    • Proposed as answer by Woohoooo Tuesday, February 21, 2012 8:25 PM
    • Edited by servy42 Tuesday, February 21, 2012 9:06 PM
    • Marked as answer by Bob Shen Monday, March 5, 2012 2:23 AM
    Tuesday, February 21, 2012 8:21 PM