As I understand value types versus reference types, value types are allocated on the stack, so a value type object is cleared from memory once the function instantiating said object terminates. This means that in the following code:

a copy of the local variable wint is added to weightedInts whereas the local variable itself is removed from memory after AddWeightedIntToList is completed.

First of all: is this correct?

Secondly, where does this copy of wint get stored? It can't be on the stack, since then it would be gone once the function completed (right?). Does this mean that the copy is stored on the heap along with weightedInts? And is it garbage collected after being removed, as if it were an instance of a reference type?

It's certainly possible that this question is answered in an article somewhere, in which case, a link to that article would be a totally acceptable answer. I just haven't had any luck finding it.

Value types are NOT allocated on the stack. Local variables of value type which are not in an iterator block or closed over by an anonymous function can be allocated on the stack and are often allocated on the stack, but they need not be. They could be allocated on the heap, or they could be allocated in registers.
–
Eric LippertOct 5 '09 at 19:54

2 Answers
2

Secondly, where does this copy of wint get stored? It can't be on the stack, since then it would be gone once the function completed (right?). Does this mean that the copy is stored on the heap along with weightedInts? And is it garbage collected after being removed, as if it were an instance of a reference type?

Your instance of List<WeightedInt> creates an array on the heap. You're assigning a portion of that array a copy of your value type when you "add" it to the list. The value is saved on the heap, as part of an array (internal to the List class).

When your weightedInts member goes out of scope, it will become unrooted, and eligible to be garbage collected. At some point after that, the GC will run, and will release the memory associated with it's internal array, thereby freeing the memory associated with your copy of wint.

Edit:

Also, when you call:

weightedInts.Remove(wint);

A few things happen (with List<T>).

First, the list finds the index of the FIRST instance of your value type that equals wint. It then calls RemoteAt(index).

The RemoveAt(index) method basically marks that the internal size is one smaller, then checks the index you're removing. If it's in the middle of the list, it actually copies ALL of the value type instances up one element using Array.Copy, to "shrink" the list. It then zeros out the memory at the end of the array.

The array itself doesn't shrink, so no memory is released by removing elements. If you want to reclaim this memory (or even make it eligible for freeing by the GC), you need to call List<T>.TrimExcess().

From what you're saying, I can conclude that the value added to weightedInts will be garbage collected once weightedInts goes out of scope. But what remains unclear to me is what happens to it if I call weightedInts.Remove(wint); -- does it remain lying around there until weightedInts is garbage collected?
–
Dan TaoOct 5 '09 at 19:26

So a list of ints would be stored in the heap and the only allocation on the stack would be the pointer to the heap for the array?
–
Ty.Oct 5 '09 at 19:30

Well, it's actually a pointer to the List<T>, which internally, contains a pointer to an array and an integer value used for tracking, but yes, that's the general idea. The array is allocated on the heap, as is the array reference inside of the List<T>.
–
Reed CopseyOct 5 '09 at 19:33

@Dan, your weightedInts is not garbage collected when it goes oiut of scope, it's garbage collected at sometime after it has gone out of scope. (Which in most cases does not make a differance)
–
Rune FSOct 5 '09 at 20:25