Hey guys , i got a few questions about C# and the using statement
Lets say we got this 2 classes
Spoiler:
PHP Code:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;
namespace UsingTesting { class Program { static void Main(string[] args) { System.Timers.Timer Tick = new System.Timers.Timer(1); Tick.Elapsed += new System.Timers.ElapsedEventHandler(Tick_Elapsed); Tick.Start(); int x = 0;
Testing s = new Testing(); s.Write(x); s = null; /* using (Testing s = new Testing()) { s.Write(x); } */
public class Testing : IDisposable { private short[] s = new short[short.MaxValue]; private short[] crap = new short[short.MaxValue];
public void Write(int x) {
short[] data = new short[short.MaxValue]; // To Take Memory Console.WriteLine("Done {0}",x);
}
public void Dispose() { s = null; // crap = null; } }
Questions 1:
In case you create something in a method (Method Write in class Testing):
Does the part of:
PHP Code:
short[] data = new short[short.MaxValue]; // To Take Memory
Automaticly gets nulled afther the method is finished?
Question 2: (See my second reply, 2 posts below if this is to shitty writen)
In case you forget to null something with the using statement, why doesn't the GC take it?
PHP Code:
private short[] crap = new short[short.MaxValue];
this is the code i forgot to "null", when the code is finished, the Memory stays at 174 KB, however if i null it the Memory stays at 110 KB, (I am spamming the GC), So why doesn't The GC take the value?
Question 3:
Is this always better then a using statement:
PHP Code:
Testing s = new Testing(); s.Write(x); s.Dispose(); s = null;
03-06-13
Komakech
Re: Few Questions about C# Using statement
Hi Hilia,
I have not worked with C# in a while so I might be a bit rusty and apologise if anything I have written is incorrect - hopefully people will correct me!
To my understanding the Garbage Collector is not instant, no matter how much you run it, if the data is considered still in use it will not clear it from memory. The way to test this is run the application and let it sit for at least 10 minutes, if it stays at 110kb instead of dropping it then the 110kb is probably the general amount the application holds in memory for other tasks?
I have no individually answered your questions as I am not 100% certain on their answers, instead I have provided what I remember of C#.
Hope this all helps and if anyone spots anything wrong (or all of it wrong) please quote it and let me know what's wrong so I can amend/point out it's wrong.
All the best,
Richard Komakech.
03-06-13
Hilia
Re: Few Questions about C# Using statement
Thnx for your answer, but what i am trying to say (srry if my english is that bad xD)
When i run this code:
PHP Code:
Testing s = new Testing(); s.Write(x); // s.Dispose(); this is not optional (nulling the whole instance) s = null;
The totalMemory comes at 110KB afther this is done.
When i run this code and didn't null the Array in Dispose:
PHP Code:
using (Testing s = new Testing()) { s.Write(x); }
The TotalMemory comes at 174 KB. Then my question is, why doesn't the GC collect the Array when the using statment is done? (The data isn't in use any more ,right?) (If i null the Array in the Dispose Method it comes at 110KB)
PHP Code:
private short[] crap = new short[short.MaxValue];
03-06-13
שเ๒єtгเ๒є
Re: Few Questions about C# Using statement
As first, the GC of the .NET cannot be controlled by yourself. By nulling any member or instance you simply tell the GC to allow to discharge it out of the memory when the GC knows it will not be called again and the memory and CPU activities are very low so it will not interfere into other process' speed or when the memory is too full for other ressources.
It's clearly unproductive to waste CPU and memory usage to clear small amounts over and over again than waiting for real necessary or simply idle situations and discharge (huge) collections of unused data from the memory at once.
Quote:
Originally Posted by Hilia
In case you create something in a method (Method Write in class Testing):
Does the part of:
PHP Code:
short[] data = new short[short.MaxValue]; // To Take Memory
Automaticly gets nulled afther the method is finished?
Yes. In this case, data is a local member of Write, so it will be nulled when the method is finished.
Quote:
Originally Posted by Hilia
In case you forget to null something with the using statement, why doesn't the GC take it?
PHP Code:
private short[] crap = new short[short.MaxValue];
this is the code I forgot to "null", when the code is finished, the Memory stays at 174 KB, however if I null it the Memory stays at 110 KB, (I am spamming the GC), So why doesn't The GC take the value?
By disposing an instance of a class, you automatically set all its non static members to null. However to null something separately in the dispose method makes still sense. Imagine your class is using static members or external resources that are not directly referenced to the class instance where calling Dispose(). So in case your class is going out of scope, you should null those additional data, because your instance cannot know it will be out of scope neither it was the the only assigned class to the additional data. Here you should keep in mind: Nulling is not discharging, as written in the first part of my post.
Quote:
Originally Posted by Hilia
Is this always better then a using statement:
PHP Code:
Testing s = new Testing(); s.Write(x); s.Dispose(); s = null;
No. By using the using statement you cannot forget disposing it without leading to a syntax error that will not allow you to compile your application. This will not allow you to keep unused data in your memory that is pretty neat.
03-06-13
Hilia
Re: Few Questions about C# Using statement
Quote:
Originally Posted by VibeTribe
By disposing an instance of a class, you automatically set all its non static members to null. However to null something separately in the dispose method makes still sense. Imagine your class is using static members or external resources that are not directly referenced to the class instance where calling [i]Dispose()[i]. So in case your class is going out of scope, you should null those additional data, because your instance cannot know it will be out of scope neither it was the the only assigned class to the additional data.
[b]Here you should keep in mind: Nulling is not discharging, as written in the first part of my post.
So if i am getting it good:
Afther this:
PHP Code:
using (Testing s = new Testing()) { s.Write(x); }
The Instance of Testing "s", gets out of scope, and because of that the GC can't "clear" the array that i forgot to "null"?
03-06-13
שเ๒єtгเ๒є
Re: Few Questions about C# Using statement
Quote:
Originally Posted by Hilia
So if i am getting it good:
Afther this:
PHP Code:
using (Testing s = new Testing()) { s.Write(x); }
The Instance of Testing "s", gets out of scope, and because of that the GC can't "clear" the array that i forgot to "null"?
Im sry, I meant No (I was misreading your question, so I edited my previous post.)
Due reaching the end of the using statement s will be out of scope, so it will null the array in any case.
But to null anything will not lead the GC to instantly discharge it from memory, however. You cannot control what you want to do and this is good, because your idea is rather unproductive than productive.
By the way: By saying "out of scope" I am talking about the instance s and all non static external data that is not apart of s (or all static data) that was only used by Testing and will not be used again, like static members of s.
Those data need to be nulled in Dispose() of Testing when no external data accesses it in any case. So you can prevent memory leaks.
Other things are unnecessary and will only increase code line amounts. In your sample code, you should not null anything so far and take the advantage of the using statement always.
03-06-13
Hilia
Re: Few Questions about C# Using statement
Quote:
Originally Posted by VibeTribe
Im sry, I meant No (I was misreading your question, so I edited my previous post.)
Due reaching the end of the using statement s will be out of scope, so it will null the array in any case.
But to null anything will not lead the GC to instantly discharge it from memory, however. You cannot control what you want to do and this is good, because your idea is rather unproductive than productive.
By the way: By saying "out of scope" I am talking about the instance s and all non static external data that is not apart of s (or all static data) that was only used by Testing and will not be used again, like static members of s.
Those data need to be nulled in Dispose() of Testing when no external data accesses it in any case. So you can prevent memory leaks.
Other things are unnecessary and will only increase code line amounts. In your sample code, you should not null anything so far and take the advantage of the using statement always.
I am going to try it again:
PHP Code:
using (Testing s = new Testing()) { s.Write(x); }
Afther the using statement is done, the instance of Testing "s", gets out of scope and all its non static members are getting "nulled", however because it goes out of scope. The GC thinks its still there and gives the wrong amount of memory?
PHP Code:
GC.GetTotalMemory(false);
04-06-13
שเ๒єtгเ๒є
Re: Few Questions about C# Using statement
Quote:
Originally Posted by Hilia
Afther the using statement is done, the instance of Testing "s", gets out of scope and all its non static members are getting "nulled", however because it goes out of scope. The GC thinks its still there and gives the wrong amount of memory?
The GC does not "think" its still there, its just still there cuz the GC doesnt discharge it from memory. And the GC know about it and will care of it, when you need more memory or close your application absolutely. It cannot be told easier my dear. :)
GC.GetTotalMemory returns the closest amount of managed bytes by the GC, there is no guarantee for a valid value. Passing true allows to wait for the GC to finalize unused objects, so passing false is not right in any case.
Quote:
If the forceFullCollection parameter is true, this method waits a short interval before returning while the system collects garbage and finalizes objects. The duration of the interval is an internally specified limit determined by the number of garbage collection cycles completed and the change in the amount of memory recovered between cycles. The garbage collector does not guarantee that all inaccessible memory is collected.
The GC does not "think" its still there, its just still there cuz the GC doesnt discharge it from memory. And the GC know about it and will care of it, when you need more memory or close your application absolutely. It cannot be told easier my dear. :)
GC.GetTotalMemory returns the closest amount of managed bytes by the GC, there is no guarantee for a valid value. Passing true allows to wait for the GC to finalize unused objects, so passing false is not right in any case.
Why I think you are confused
In unmanaged programming, we often have to deal with the deletion of objects in order to prevent memory leakages. For example in unmanaged C++, we ofted use the "free(void*)" function or the "delete" keyword to unallocate objects stored in memory, so as to free up memory for other objects.
In managed programming, this unallocation of memory is managed (hence the name "managed programming") by a mechanism called the Garbage Collector. Objects which would not be used anymore are marked (by the program) for deletion by the Garbage Collector. The Garbage Collector will then collect these garbage whenever it does its rounds, but not necessarily immediately. However, the interval at which the Garbage Collector collects and deletes these garbage is unknown, and since all these garbage collection is neatly managed in managed programming, we should aim to not interfere nor interact with the Garbage Collector. One of the purpose of managed programming languages is, in my personal opinion, after all to allow developers to develop faster and more efficiently without having to worry about memory leakages.
Question1:
After the program leaves the scope (in this case, the method) in which the array was created in, the program marks this array for deletion by the Garbage Collector. It will be deleted (I.E. nulled) only when the Garbage Collector does its rounds.
Question2:
Again, the Garbage Collector will only collect garbage and delete them when it does its round. When the using statement is done, the array is marked for deletion. But it will not be deleted immediately. It will only be deleted when the Garbage Collector does its rounds.
Question3:
It depends. If you're planning to pass the object somewhere else (E.G. returning it to the caller from a method) before disposing it, then its easier to call dispose(). However, if the object is created and disposed in the same scope, we generally prefer to use the using keyword.
Summary:
Don't worry about deletion of objects which are no longer used. In fact, please aim to worry as little as you can about where how, when, where your objects are stored and how, when, where your objects are deleted. Managed programming languages generally provide a good mechanism to manage such memory related issues. The GC.Collect() method allows you to force the Garbage Collector to immediately collect and delete all marked garbage, if you find a need to. However, this interferes with the Garbage Collector, and as I've said, it is generally sinful to do so.