2

I am sorry if "Safe" is a missleading word, I was not sure what word to use in this situation. I was wondering if for instance using

 public static List<myObj> myList = new List<myObj>();

is acceptable in C#. Static variables stick around in the RAM throughout the life cycle of the application no matter what, so for instance in applications such as ASPX, this can lead to some unwanted behavior and the GC will not collect the allocations.

I have noticed that if I have a list of objects, which is static, in say a static "global" class ie.

 globl.myList.add(foo);

then they stay throughout the life of the application. Does this mean that if I have a static list of objects, then the objects themselves which are appended to the list are static themselves, or is it because there is a reference to them, the GC does not collect them? In other words, if I remove an element, will the GC collect it later or is it going to be stuck in the heap until the application dies?

Thanks ahead of time!

Serguei Fedorov
  • 7,763
  • 9
  • 63
  • 94

5 Answers5

4

Safe is a very, very dubious term here. Safe in what context?

Is it safe in terms of memory: mostly yes. Adding a reference to a static list will still be collectable if that reference is later removed and no one else refers to it, so adding an item to a static list, in of itself, does not prevent it from being collected.

Now, that said, if the item is held by the static list for a long time before all references are gone, it may be promoted to later generations in the GC lifecycle, which may make memory clean-up of the item a lot slower once all references are released.

Is it safe in terms of thread safety: mostly no. If the list is modifiable while other threads can read it, then you will need to synchronize access to it. That said, if the list is loaded on creation, multiple threads can access it in a "read-only" manner safely.

And, if you do need concurrent access to a mutable collection, consider the Concurrent Collections in .NET 4.0 instead (MSDN)

James Michael Hare
  • 37,767
  • 9
  • 73
  • 83
  • I was not sure what word to use but I can see where the confusion is coming from. However you answered my question. I was wondering if the elements inside get removed from the heap once they are unlinked from the list. – Serguei Fedorov Oct 26 '12 at 15:29
  • @SergueiFedorov: A `List` is essentially a *vector* or "dynamic array" if you will. This means as you add items to the list, it will grow its internal memory to hold those items, and if you remove an item, it will shift them down. However, it typically will *not* reallocate a shorter array on removes. This generally isn't an issue, though. If you **really** want to remove the excess capactiy from a list, you can call `TrimExcess()` on the list and it will size it to exactly the capacity needed to store the current items. Beware, though, that it is a O(n) operation. – James Michael Hare Oct 26 '12 at 15:37
  • Good to know! For some reason I've always assumed that a list in C# is an implementation of a Linked List rather than a vector. Good thing to know for an interview! – Serguei Fedorov Oct 26 '12 at 15:50
  • @SergueiFedorov: Nope, but C# does have one! `System.Collections.Generic.LinkedList` - http://msdn.microsoft.com/en-us/library/he2s3bh7.aspx – James Michael Hare Oct 26 '12 at 15:52
1

Negative. As long as the reference is being held in this manner, the GC will not collect the references in your list.

The object's themselves are not "static" per se - they simply exist in relation to a static reference.

Tejs
  • 40,736
  • 10
  • 68
  • 86
1

Only the List is static. The objects are not. If you remove an object and there are no other references to that memory, then it becomes a candidate to be garbage collected.

Candide
  • 30,469
  • 8
  • 53
  • 60
1

Static variables stick around in the RAM throughout the life cycle of the application no matter what

They are in memory for the life of the AppDomain - which for IIS means the life of the AppPool. IIS will recycle AppPools periodically so there's no guarantee that the data will stay in memory indefinitely.

Does this mean that if I have a static list of objects, then the objects themselves which are appended to the list are static themselves, or is it because there is a reference to them, the GC does not collect them?

no, the object are not static - they are not collected because there is a reference to them.

if I remove an element, will the GC collect it later or is it going to be stuck in the heap until the application dies?

If will not be collected as long as something holds a reference to it. If the list is the only thing reference it it is eligible for GC once it's removed from the list.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
0

if I remove an element, will the GC collect it later or is it going to be stuck in the heap until the application dies?

You can create the experiment, you can write a programm which load big image like bitmap and add it to list, and remove it from list and after that start gc collect, and you can see in task manager (cntr+shift+esc) memory consumption of your app. for example:

class Program
    {
        public static List<Bitmap> Bitmaps = new List<Bitmap>(); 

        static void Main(string[] args)
        {
            Bitmaps.Add((Bitmap) Image.FromFile(@"C:\\image.bmp")); // the size of image 23 mb (in that case), you will see in task manager that you app start consumes a lot of memory
            Console.WriteLine("Memory state after loading image in list");
            Console.ReadKey();
            Bitmaps.RemoveAt(0);
            GC.Collect();
            Console.WriteLine("Memory after collect"); // and after deletion from list and start gc you will see that your app consume  less memory
            Console.ReadKey();
        }
    }

It mean that GC will collect your element after removing from list.

testCoder
  • 7,155
  • 13
  • 56
  • 75