C# Question

This is a question for you C# gurus out there.

If I have code that does this:


private static string testString = "Test";
private Hashtable hashTable1 = new Hashtable();
private Hashtable hashTable2 = new Hashtable();
hashTable1.Add(0, testString);
hashTable2.Add(0, testString);

Will the two string values stored in the hash tables reference the static string, or will they each get their own copy?

they will both reference the same string since the hashtable is storing references.

That should be easy to test. I think same reference.

Did a quick test:

        Dim myString As String = "test string"
        Dim hash1 As New Hashtable
        Dim hash2 As New Hashtable
        hash1.Add(0, myString)
        hash2.Add(0, myString)
        Console.WriteLine("Hash1={0} Hash2={1}", CType(hash1(0), String), CType(hash2(0), String))
        myString = "Did it change"
        Console.WriteLine("Changed string")
        Console.WriteLine("Hash1={0} Hash2={1}", CType(hash1(0), String), CType(hash2(0), String))
        Console.ReadKey()

Produced

Hash1=test string Hash2=test string
Changed string
Hash1=test string Hash2=test string

Jas

-Comment removed-

@ Jas You can’t test it like that. After you assign a new value to the myString variable it references completly new object.

Thank you for your answers.

@ Architect - I think you are right, but I’m not sure how to test it.

@ Jas - I agree with @ Architect, once you reassign a value to a string it will no longer point to the same object. Strings are unique that way, in that they are both a reference type and a value type.

In my application I need to create many dozens of objects that contain constant strings that are identical to each other, and I want to minimize the memory used.

Well, you can compare hash value of each object in the tables.

Ahh! Good idea. - I’ll try something later today.

Yes, but I don’t think that’s the root of the problem with Hashtables. If you notice, the Add() takes an “object” type parameter. This means that whatever type you send it is going to be cast to an immutable type. Change “myString” in Jas’ example to an int type which is normally mutable and you’ll get the same result.

If you need a mutable collection then use a Dictionary<key,val> type or an array. A Dictionary<> where the key is equal to the hash value of the type would more or less give you the same thing as a Hashtable although performance may not necessarily be quite equal. It would be interesting to compare.

You can see if the same string object is referenced in the hashtables by doing the following comparison

if (hashTable1[0] == hashTable2[0])
      ...  

if you wanted to see if the contents of the strings are the same you would do the following:

if (((String)hashTable1[0]).Equals((String)hashTable2[0])))
     ...

I need to rephrase this:

To this:

Strings are unique that way, in that they are reference types, but sometimes behave as if they were value types.

For example given:


int intA = 0;
void functionX(int x) { x = 1; }
void functionY(ref int y) { y = 1; }

You would expect that calling functionX(intA) would not alter the value of intA,
and calling functionY(ref intA) would change intA’s value to 1;

Strings behave the same way:


string stringA = "A"
void functionX(string x) { x = "X"; }
void functionY(ref string y) { y = "Y"; }

Calling functionX does not change the value of stringA, but calling functionY does.

@ Ian - please explain further. Would you agree that both hashtables will contain references to the original string, or will they end up with their own immutable copy?

Calling functionX does not change the value of stringA, but calling functionY does.

In functionX, a copy of the reference was put into the stack and passed to the function. When you changed the value of x, you changed the value on the stack.

In functionY, by using the ref modifier, you told the compiler you did not want a copy of the reference on the stack. You wanted the function to directly access the reference for reading and writing.

Thanks @ Mike - I have to go to work now, but I’ll test that later today.

Both have references to original string.

For formal discussion on this subject, google for" passing by value versus by reference".

I don’t think so. Jas’ example clearly demonstrates that they each get their own copy.

It doesn’t demonstrate that. Mike is right. References in both cases.

As for Jas’s example. In both cases strings are passed as references. In first case another variable is created that references the same string. In second original variable is used.

Duh! Mike is wrong!

*** Edited. The only time I make a mistake is when I think I made a mistake. I was not wrong. :-[