Share via


De-Allocate Dictionary Memory in C# best practice

Question

Wednesday, May 7, 2014 11:42 AM

I've been doing some research on best practices for de-allocating Dictionary resources in C#.

I have an MVP (View, Presenter, Controller) Pattern in an asp.net app that's using 2 dictionary objects to send to our controller for a database update and am wondering if we set the dictionary objects to null, that will release the object from memory.

The dictionary is declared in our IView Interface like this:

//two dictionary objects passed to insert/update functions in controller
Dictionary<int, int> GroupValues1 { get; set; }
Dictionary<int, DateTime> GroupValues2 { get; set; }

And implemented in our asp.net codebehind like this:

public Dictionary<int, int> GroupValues1 
{
get
      {
            object obj = ViewState["_dictionaryGroupValues1"];
            return (obj == null) ? null : obj as Dictionary<int, int>;
}
set {ViewState["_dictionaryGroupValues1"] = value;}
}
        
//second parameter to submit-INSERT, Update
public Dictionary<int, DateTime> GroupValues2
{
get
{
object obj = ViewState["_dictionaryGroupValues2"];
return (obj == null) ? null : obj as Dictionary<int, DateTime>;
}
set{ViewState["_dictionaryGroupValues2"] = value;}
}

Here they are referenced in our presenter:

public bool UpdateRetentionGroupData() {
return _controller.UpdateMaterialStatus(View.GroupValues1, View.GroupValues2);
}

As well as our controller.

public bool UpdateMaterialStatus(Dictionary<int, int> Dictionary1, Dictionary<int, DateTime> Dictionary2)

So I am not sure if doing something like this in our asp.net code behind will have any effect on memory or not:

GroupValues1 = null;
GroupValues2 = null;

Since it's referenced in IView, Presenter and controller.

thanks

All replies (7)

Wednesday, May 7, 2014 11:56 AM âś…Answered

Believe it or not, but setting to null can actually delay how long it takes for memory to be reclaimed rather than speeding it up.  .net manages its own memory via scope and garbage collection, you have to just let it do its thing.  The only thing you have to concern yourself with is that you Dispose anything that supports the Dispose interface.  Other than that, don't worry about it.

Getting back to my opening point, if your code is like this;

void function()
{
    Person p = new Person();

    p.FirstName = "John";
    p.Save(); // ****

    // other code
}

void function()
{
    Person p = new Person();

    p.FirstName = "John";
    p.Save();

    // other code

    p = null; // ****
}

The lines I have marked with **** are the lines at which "p" becomes available for garbage collection.  In the first example, the object is marked as unused after the call to Save as that is the last time it is referenced in your code.  In the second example, as you reference the variable later on (even though you are setting it to null), it is then that the object is marked unused as that is your last reference.

The moral of the story is that .net and compiler optimisation are way celever than you are so let them do their job :)


Wednesday, May 7, 2014 12:24 PM

Another question that was posed, is: Will this memory be de-allocated when web session expires?

thanks in advance.


Wednesday, May 7, 2014 3:42 PM

No, it's just allocated memory.... .net has no idea where it has come from, it all sits in the same pot waiting to be deallocated.  If you have things in the session, then they will get disposed and will be available for collection when the session expires, but nothing happens instantly when the session expires.


Thursday, May 8, 2014 12:27 AM

A small point

at which "p" becomes available for garbage collection

"p" is not subject to garbage collection, it is a local variable.  "The actual lifetime of a local variable is implementation-dependent" (C# standard 5.1.7).  The general assumption is that when the enclosing block ends the memory allocated (perhaps on the stack) is released (unless the variable has been captured by an anonymous function).   The 'new Person()' that "p" references is what takes up space and is what will be eventually garbage collected.  The standard says "The storage referred to by a local reference variable is reclaimed independently of the lifetime of that local variable" (5.1.7)  There may be multiple variables "p", "q", etc which reference the same 'new Person()'.  It is only at the point where there are no longer any references to the object that it becomes available for collection.

I think your example that setting to null can delay the reclamation of memory may be wrong (not sure).  I think the picture would be better explained like this

void function()
{
    Person p = new Person();

    p.FirstName = "John";
    p.Save();
    // other code
} // ****

void function()
{
    Person p = new Person();

    p.FirstName = "John";
    p.Save();

    // other code

    p = null; // ****

    // other code

}

In the first case the 'new Person()' is not available for GC until there are no longer any references to it.  "p" will refer to the object right until the point that the stack is cleaned up at the end of the method.

In the second case there are no longer any references to the 'new Person()' object at the point where anything else is stored in "p".  It could be null or it could be another 'new Person()'.

 

The common (although not 100% correct, I think) usage is to say that "p" is allocted on the stack and goes out of scope when the stack is cleaned up on method exit.  The 'new Person()' is allocated on the heap and is available for GC when there are no more references to it.

The moral of the story is that .net and compiler optimisation are way celever than you are so let them do their job :)

Agree 100%


Thursday, May 8, 2014 5:31 AM

"p" is not subject to garbage collection, it is a local variable.

Yes I know, my reply was targetted at the OP using terms\concepts they are more likely to understand so they get the gist of what is going on without having to get into explanations of stacks and heaps.  I don't think being pedantic over these matters really adds anything to the thread.

I think your example that setting to null can delay the reclamation of memory may be wrong (not sure).

p never goes out of scope until the function terminates so Person is always referenced until the end of the function.  The compiler optimisation, however, analysis the code and pre-empts the availability for garbage collection at the point is knows the referenced variable is never referred to again.  It is of little help in properly-written websites (as functions are designed to be short-lived), but consider desktop applications where a function may take some minutes to complete, or a service where it may take hours.  The optimiser employs these techniques to avoid objects hanging around in memory when they are no longer needed despite them still being referenced.

 


Thursday, May 8, 2014 5:38 AM

That's better.  But I still think that if you don't set to null then you are relying on something that is described in the Language Specification as 'implementation dependent' (eg.  could go away or change at any time or be different for different compilers) whereas if you set "p" to null you are operating within the guaranteed behaviour of the language and the garbage collector.

It really is a big nothing but I find that people get confused about the details because they hear half the story.


Thursday, May 8, 2014 6:10 AM

I'm not bothered in the slightest that not setting to null relies on something that is implementation dependent.  I'd rather understand how the optimiser works and work with it, and follow Microsoft coding standards.  Even look at code samples, where do you see things set to null?  Setting to null is an artifact from reference counting implementations (eg COM) as reference counting isn't incredibly reliable.  Back then we set to null due to implementation dependence, now we don't do it because of implementation dependence, due to how garbage collection is implemented which makes setting to null redundant, and not only redundant but it interferes with code optimisation too.  In this less-than-ideal world we live in that's just how it goes, regardless of what the language spec says.