Storing a struct or class in a hashtable and modifying it.

B

Bill

Hello,

Here is some code:

I'm thinking that when storing an object in an ArrayList or Hashtable
that it clones the object. This can be shown like so:

// key is a generated hashcode for this function (its unique).

public struct Test {
int m_state;
}

p_newItem.m_state = 0; // Set the state
m_myHash.Add( (object) key, (object) p_newItem); // Store the object in
the hashtable
p_newItem.m_state = 1; // Now change the value

Test t = (Test) m_myHash[ (object) key ];

Console.WriteLine( t.m_state ); // != 1 its still 0!!


What is going on here? My only guess is that the object is stored as a
clone of the original. Not as a reference as I would expect.
 
J

Jeff Louie

Bill... You are using a struct which has value semantics. When you pass
a value type to a method you get a copy of the value, not a copy of a
reference. When you pass a value type to a collection it gets boxed. I
would think you would get a reference to a boxed _copy_ of the value.

Regards,
Jeff
What is going on here? My only guess is that the object is stored as a
clone of the original. Not as a reference as I would expect<
 
B

Bill

Jeff said:
Bill... You are using a struct which has value semantics. When you pass
a value type to a method you get a copy of the value, not a copy of a
reference. When you pass a value type to a collection it gets boxed. I
would think you would get a reference to a boxed _copy_ of the value.

Regards,
Jeff


clone of the original. Not as a reference as I would expect<

If I change it to a class ( which was the original plan ) it still has
the same behaviour. Is there anyway around it?

- Bill
 
J

Jeff Louie

Bill... Does this code make sense?

using System;

namespace TestHash
{
class Test
{
public int i=0;
}
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
System.Collections.Hashtable h= new System.Collections.Hashtable();
Test t= new Test();
h.Add("one",t);
Test t2= (Test)h["one"];
System.Console.WriteLine(t2.i); // output 0
t.i=1;
t2= (Test)h["one"];
System.Console.WriteLine(t2.i); // output 1
System.Console.WriteLine(t == t2); // output true
System.Console.ReadLine();
}
}
}


Regards,
Jeff
If I change it to a class ( which was the original plan ) it still has
the same behaviour. Is there anyway around it?<
 
B

Bill

Here is a short simple example.


using System;
using System.Collections;

namespace Interface
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class TestApp
{
public struct Test
{
public int m_state;
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{

Hashtable m_myHash = new Hashtable (71);

Test p_newItem = new Test();

p_newItem.m_state = 0; // Set the state
m_myHash.Add( (object) 5, (object) p_newItem); // Store the object in
the hashtable
p_newItem.m_state = 1; // Now change the value

// t should be the exact same object as p_newItem. Not a clone.
Test t = (Test) m_myHash[ (object) 5 ];

Console.WriteLine( "Stored state is " + t.m_state ); // != 1 its
still 0!!

Console.ReadLine();
}
}
}
 
J

Jon Skeet [C# MVP]

Bill said:
Here is a short simple example.

Your Test type is still a struct though. Change it to a class, like we
suggested, and you'll see different behaviour.
 
B

Bill

Jon said:
Your Test type is still a struct though. Change it to a class, like we
suggested, and you'll see different behaviour.
That was it. I missed the part in the .net manual that said that structs
were from System.ValueType and classes where always from Object ( and
therefore passed as references ).

Thanks for the help.

- Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top