struct with string, where does it allocate to? heap?

H

haitao.song

Hi,

As it is always stated that value type is allocated on stack, while
reference types are on managed heap. How about the struct with
string members?
stuct A { string str; }

String type is considered as reference type.... My guess is the
struct A is actually a valuetype with a string reference/address.
So it acts as if struct A { int ptrStr; } Anyway, the ptrStr is like a
pointer (integer value) to a non-mutable reference string on heap.

Some suggestions? How does it work? Under GC, does all copies
of A gets updated with the string reference value?
 
H

haitao.song

using System;

using System.Collections.Generic;

using System.Text;

namespace construct

{

class Program

{

public struct A

{

private string str;

public string Str

{

set { this.str = value; }

get { return this.str; }

}

}

public class B

{

private string str;

public string Str

{

set { this.str = value; }

get { return this.str; }

}

}

public static void fooA(A a)

{

a.Str = "Assigned FooA";

}

public static void fooB(B b)

{

b.Str = "2";

}

static void Main(string[] args)

{

A ast = new A();

B bst = new B();

ast.Str = "1";

fooA(ast);

fooB(bst);

System.Console.WriteLine(ast.Str);

System.Console.WriteLine(bst.Str);

System.Console.ReadLine();

}

}

}


---- Looks like it does allocate on stack
 
B

Bruce Wood

As it is always stated that value type is allocated on stack, while reference types are on managed heap.

A lot of books state this. It is an oversimplification. The truth is:

1. Reference types are allocated on the managed heap.
2. Value types that are local variables or method parameters are
allocated on the stack. This includes references to reference types
(which are, themselves, just values).
3. Value types that are members of a reference type (for example the
"int"s that form part of an object's state) are allocated along with
and in-line with all of the other data for the reference type, on the
managed heap.

Your assumption about a value type that contains a reference to a
string is correct: the values that make up the value type will be
allocated wherever that value type is allocated. If it is a local
variable or a method parameter, on the stack. If it is a member in a
class definition, then on the heap with the rest of the data for the
class.

The value type will contain as part of its value a reference to the
string, which will be allocated on the managed heap.

Remember that strings are immutable, so one cannot make a change to the
string and have all value types that reference it change together,
although your assumption that all value types point to the same string
on the heap would be true (depending upon how the string was
constructed and how its reference is placed in the struct).

Your theory works out better if you choose something other than a
string. Take, for example, a value type that is a Measure:

public struct Measure
{
private decimal _quantity;
private UnitOfMeasure _units;

public Measure(decimal quantity, UnitOfMeasure units)
{
...
}
}

Assuming that UnitOfMeasure is a reference type, then the struct will
contain: a decimal value, and a reference. If multiple Measures are
constructed pointing to the same UnitOfMeasure, then they all contain
the same reference to the same unit of measure object on the managed
heap.

If the UnitOfMeasure class were mutable (a bad idea, in this case, but
say it were) then a change to a unit of measure object would have an
effect in all Measure structs that point to it, just as you surmised.
That's why I made my UnitOfMeasure class immutable. :)
 
H

haitao.song

using System;

using System.Collections.Generic;

using System.Text;

namespace construct

{

class Program

{

public class IntClass

{

private int x;

public IntClass() { x = 0; }

public int Val { get { return x; } set { x = value; } }

}

public struct A

{

private IntClass xint;

public void setInt() { xint = new IntClass(); }

public IntClass XInt

{

set { this.xint = value; }

get { return this.xint; }

}

public int X

{

set { xint.Val=value; }

get { return xint.Val; }

}

}

public static void fooA(A a)

{

a.XInt = new IntClass();

}



static void Main(string[] args)

{

A a = new A();

a.setInt();

a.X = 6;

fooA(a); // should still be 6;

System.Console.WriteLine(a.X); //6

A b = a;

b.X = 5;

System.Console.WriteLine(a.X); // both to 5
System.Console.WriteLine(b.X); // both to 5

b.XInt = new IntClass(); // the reference wont get updated into all
copies of the value types.
System.Console.WriteLine(a.X); // 5
System.Console.WriteLine(b.X); // 0

System.Console.ReadLine();

}

}

}
 

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