This is complicated, but simple, all at the same time.
The simple version?
The destructor is only called for unreferenced objects, and the third item you created is still referenced: the local variable
still contains it.
To prove that, kill the reference inside the loop:
static void Main(string args)
for (int i = 0; i < 3; i++)
Class1 c = new Class1();
c = null;
And you will get three calls to the destructor.
The complicated bit is that you think the variable
has been dereferenced - but it hasn't been, it's just gone out of scope.
That's not the same thing: the variable is allocated on the stack when the method is called, not when it is declared (so that regardless on the path through the method the number of stacked items to be removed is the same) so scope doesn't effect actual existence!
That's actually worth remembering: if you need a lot of variables (or some really big
s) in a single route through the method but not in others and stack space is at a premium the it's worth moving that path outside the method and into it's own ...
(But remember that an array of anything is a reference value, so it's on the heap anyway, except for the variable which references the array itself.)