0

Let's say I have the following code:

float[] test = new float[10];
for(int i = 0; i < 10; i++)
{
     test[i] = i + 1.0f;
}

and I reassign a new float to test array like this:

test = new float[10];

After debugging through Console.WriteLine, it shows that the value of the reassign test is 0. Does that mean test is a reference to a newly created float array, or the previous array is being cleared and recreate again?

I have read some articles about heap and stack but that didn't resolve my confusion.

9
  • 4
    "a newly created float array" - that. The array itself is a reference type, so the old reference is lost. The original values are sitting in the array until GC'd but you can't get to them. You're seeing the new array and default values in each element. Commented Feb 25, 2020 at 11:08
  • 1
    You create a new instance of array of floats (with default values) and assign the reference to it to the test variable Commented Feb 25, 2020 at 11:08
  • 4
    Don't worry, the stack is an implementation detail. It's the semantics of values vs. references that matter. Commented Feb 25, 2020 at 11:15
  • 2
    @nicklowkc - madreflection's given you a good start. Eric Lippert writes carefully and accurately about the subject. Commented Feb 25, 2020 at 11:20
  • 1
    You're welcome. Don't forget to go back and read part two after you've had time to digest part one. Commented Feb 25, 2020 at 11:25

2 Answers 2

6

Deep down, test is a pointer to a chunk of memory of size sizeof(float) * 10) (the chunk might be a bit larger, but that is outside the point).

Within the loop, you start putting values within that chunk of memory. Then, when you do test = new float[10];, the CLR will give you a new pointer to a new chunk in memory.

The previous chunk in memory will be reclaimed by the garbage collector (unless it is being used some place else) at some point in the future.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi, thank you for you reply. I tested it by creating a new float array and assign it to the old array and it works! So memory being reclaimed by the GC is not predictable am I right? Does it cost performance when GC collects the memory?
Predictable? No. But it's even crazier than that. Managed memory simulates a computer with infinite memory. A correctly written program cannot assume that memory will ever be collected (as a corollary to the point made in this article...) Everybody things about garbage collection the wrong way.
GC is usually best left to be triggered automatically as needed. It then happens when the system wants to garbage collect. You can induce garbage collection by GC.Collect(), but not generally recommended. A GC has a cost, yes. You can measure GC cost by running perfmon and adding counters for .NET CLR memory. % time in GC for example - then play around with some intensive memory processing. GC may be predictable, it may well seem to happen according to a pattern, but it is not guaranteed and can change at anytime.
@nicklowkc: As it has been said, yes, there is a performance hit usually when GC kicks in, however this is usually seen as a necessary evil since once that the GC is done the application has more memory to use. As it has been said, it is usually best to leave the GC to its own devices, and not mess with it.
0

Let me give you a more detailed example:

float[] test = new float[10];
float[] test2 = new float[10];

test = Enumerable.Range(10, 10).Select(x => (float)x).ToArray();// 10 - 20
test2 = Enumerable.Range(20, 10).Select(x => (float)x).ToArray();// 20 - 30

float[] testBak = test;
test = test2;
test[0] = 1;

Console.WriteLine(test[0]);// prints 1 as it was just modified
Console.WriteLine(test2[0]);// prints 1 because it has the same value of the reference as 'test'
Console.WriteLine(testBak[0]);// prints 10 which is the old value of test[0]

I have rewritten your code using two variables to hold both references of the arrays (which are value types). What you are doing when you are making an assignment is changing the value of the reference which that variable is holding to another value of another reference.

The memory locations which the two arrays hold are still different even after assignment, you are just keeping in your variable another address. This is why if you change the value of one of the entries in the first array, it will be visible in all the variables holding the same reference of that array, but not in the variables holding the reference of another one (as testBak holds an older reference).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.