Objects stored in a hashtable - by reference?

Hi,

I'm writing an interpreter in c#. For variables I have a system where I have a class representing a variable:


class var {public Hashtable Children;public object Value;}
 


When a variable is declared, I do something like this:


var Temp = new var();Temp.Value = something;VarIndex.Add("variable name",Temp);
 


However I've found adding the Temp object to the hashtable just adds a reference to the object - if I then use the same Temp object to store another variable in the hashtable, the first variable inherits these characteristics.

Is there any way to get the hashtable to store the whole object, not just a reference


Answer this question

Objects stored in a hashtable - by reference?

  • Raphael39913

    You're not doing what you think you're doing. Let's take a look at your Add method:

    void Add(var ToAdd)
    {
       var Temp = new var();
       Temp = ToAdd;
       hash.Add("key", Temp);
    }

    You create a local variable named Temp, create a new instance, and assign temp to point to that instance. You then point Temp to the same instance as the ToAdd parameter points to. (The var you created on the first line using "new var()" is no longer reachable and will be collected the next time the garbage collector runs.) You then add the object pointed to by Temp to the hashtable. This code will behave identically to:

    void Add(var ToAdd)
    {
       hash.Add("key", ToAdd);
    }

    What you really want to do is:
    void Add(var ToAdd)
    {
       var Temp = new var();
       Temp.Value = ToAdd.Value;
       hash.Add("key", Temp);
    }

    Note that Temp, ToAdd, and the hashtable all point to the same object contained in value. If you want to do a deep copy, you'll have to duplicate whatever is in Value.

    You might want to consider implementing the ICloneable interface on your var class. It's a more generic way to create duplicates of your objects than hand-copying properties whenever you need to duplicate the object. Then you could write:
    void Add(var ToAdd)
    {
       hash.Add("key", ToAdd.Clone());
    }


  • SavageE

    Hi,

    Thanks alot. it's as I thought, you need a separate object for each entry.

    I've been told that if I did something like this

    void Add(var ToAdd)
    {
    var Temp = new var();
    Temp = ToAdd;
    hash.Add("key", Temp);
    }

    would work ok as even though the object Temp goes out of scope at the end, garbage collection doesn't destroy it as it's being referenced. This is fine for what I need, I'll be using functions for all storing. The example where I used the same object for several was actually just for testing!

    Thanks alot

  • Jim Crayne

    Hello,

    The var is a class and not a primitive. You will need to create a clone of the object and put that in the hashtable instead of the object itself.

  • SmoothUK

    When you implement IClonable, make sure to pay attention to which member variables are value types and reference types.

    Below is a sample Clone implementation that does a deep copy of enclosed reference types.  String is a special reference type that does not need to be specially dealt with since it's immutable -- any change to the string returns a new string, so it's okay if they both point to the same place.

    class Foo : ICloneable
    {
       Foo[] _arrayofFoos;
       int _i;
       string _myStr;

       public object Clone()
       {
          // this only does a shallow-copy -- value types will be copied
          //  for reference types, the reference is copied -- i.e., they'll 
          // both point to the same object.  _arrayofFoos will be the same
          Foo f = this.MemberwiseClone();

         // make a copy of the array and all of its children
          Foo[] newArr = new Foo[_arrayofFoos.Length];

          for(int i = 0; i < _newArr.Length; i++)
          {
                newArr[ i ] = _arrayofFoos[ i ].Clone();
          }

          f._arrayofFoos = newArr;

          return f;
       }
    }


  • Christopher Fleming

    James' suggestion of implementing IClonable is probably your best bet.  Another option would be to switch from a class to a struct, which would convert your var class from "by reference" to a "by value" value type.

    -Shawn

  • Objects stored in a hashtable - by reference?