0

I'm trying to understand when a object is recycled. For example, in a class I have a List declaration and a method inside this class to populate the list by declaring and initializing a temporary object and then adding this object to the list.

My confusion: Since the temporary objects were declared within the body of the method, wouldn't these objects be recycled when the method returns and thus the list which held references to them now lose their object's values? My code still keeps the object values (and presumably reference intact) after method completion.

public class CameraTest
{

    private List <Camera> cameraList;
    public CameraTest()
    {
        AddCamera();
    }

    private void AddCamera()
    {
        Camera tempCamera = new Camera();
        tempCamera.Name="Camera1";
        cameraList.Add(tempCamera);
    }

   //Why would cameraList still have the "Camera1" object here?

}
Johan
  • 8,068
  • 1
  • 33
  • 46
JoshD
  • 21
  • 3
  • 1
    Your question would be better if you included code that can actually compile. – Matt Burland Aug 12 '15 at 15:30
  • For one, you created the variable `cameraList` as a global variable on your class. – Johan Aug 12 '15 at 15:31
  • 1
    The objects will still exist as long as you have an instance of CameraTest and you found a better place to call AddCamera - i.e. in the constructor. – user2867342 Aug 12 '15 at 15:31
  • no garbage collection only occurs when the reference count is 0 – johnny 5 Aug 12 '15 at 15:31
  • 1
    In short, an object exists and continues to exist so long as *somebody* has a reference to it (technically, it still exists until it's GC'ed). The variable `tempCamera` doesn't exist outside the `AddCamera` method, but the object you assigned to it and then added to your `cameraList` does because `cameraList` has a reference to it. – Matt Burland Aug 12 '15 at 15:32
  • Orphaned objects are collected when the garbage collector runs, not when they go out of scope. Garbage collection is expensive so the GC runs if there is a need, eg if there is memory pressure. – Panagiotis Kanavos Aug 12 '15 at 15:33
  • @Johan There is no such thing as "global variable" in C#. – BartoszKP Aug 12 '15 at 15:33
  • @PanagiotisKanavos: True, but irrelevant since `cameraList` retains a reference to the object and thus makes it ineligible for collection. – Matt Burland Aug 12 '15 at 15:34
  • I apologize, I thought using a fictional class to illustrate the point would be acceptable since it was a brief example. – JoshD Aug 12 '15 at 15:34
  • @BartoszKP fair enough, I should not have used those words. I should've explained it better with scope, etc. like the answers did.. – Johan Aug 12 '15 at 15:37

3 Answers3

6

The garbage collector in .NET is non-deterministic. An object is "ready for collection" once there are no more references to it, but that doesn't mean it'll be collected right away.

In your code, cameraList has the object with name "Camera1" in it because it references it, so it prevents it to be collected, no matter the scope.

The scope is meant for variables, not for objects. Objects are references in memory, while variables are just pointers to those references. You lose the variable tempCamera, but not the object it points to

Jcl
  • 27,696
  • 5
  • 61
  • 92
  • 2
    `An object is "ready for collection" once there are no more references to it` That's not correct. If it were you could have islands of isolation in .net. Instead you might want to write `An object is "ready for collection" when it's no longer rooted` – Conrad Frix Aug 12 '15 at 15:45
  • All the provided answers made sense, but your variable vs. object statement drove the point home. – JoshD Aug 12 '15 at 15:55
  • @ConradFrix you are of course, right, but then you'd have to explain the concept of GC root objects and an intensive course on how a GC works, which I guess would make a too long answer for a question like this one. I tried to make it simple: again, you are right, and if the OP wants to dig further, I'd recommend [this link](https://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/) but I guess the "simple although not exactly correct" explanation was enough to get started – Jcl Aug 13 '15 at 18:30
3

Simply said: a variable is just a pointer ("reference") to an object. While a variable may go out of scope, if another variable or object (such as your list) holds a reference to that same object, the object won't be garbage collected.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • *a variable is just a pointer* Is that true of all variables? – Conrad Frix Aug 12 '15 at 15:58
  • @Conrad no, that's why I said "simply said". From [MSDN: Types (C# Reference)](https://msdn.microsoft.com/en-us/library/3ewxz6et.aspx): _"Variables that are value types store data, and those that are reference types store references to the actual data. Reference types are also referred to as objects"_. – CodeCaster Aug 12 '15 at 16:24
2

Because, while CameraTest exists, it references cameraList. While cameraList exists, it references all instances of Camera that have been added to the collection.

You added the Camera1 instance of Camera to cameraList. So there's a chain of references that will prevent Camera1 from being collected by the GC until nobody holds a reference to the CameraTest instance.

You should snag a copy of CLR Via C# and read it.