-2

c# has FileStream class and wrap OS file handle. FileStream has destructor, consider we get instance from FileStream and forget it, if there aren't any refrences to it, GC must call it's destructor and release OS file handle so why it will not happen untile myself call it's dispose or application terminated?

Rahmat Anjirabi
  • 868
  • 13
  • 16
  • 1
    The GC will call the descructor. – SLaks Mar 13 '19 at 21:48
  • 2
    `will not happen untile myself call it's dispose or application terminated?` - because GC [does not run at random](https://stackoverflow.com/a/28461701/11683). Get yourself into one of the conditions under which GC runs, and it will call the destructor. – GSerg Mar 13 '19 at 21:51
  • 1
    You could easily check it out by calling `GC.Collect(); GC.WaitForPendingFinalizers();` – tukaef Mar 13 '19 at 22:05
  • 1
    In Theory you are right. But in Praxis you will never know who has a reference to this FileStream and in the context of Native code involved you does not know it even a bit more. From your side it only needs one class that has an event handler or anything else obtained from the FileStream that is also set in the FileStream to prevent it from beeing collected. – Venson Mar 13 '19 at 22:07
  • Disclaimer: _Bad Example and just guessing_: Lets just have a look at the SafeFileHandle that is stored in the `_handle` field. This comes from a native call in line 845. This is also a class that is might be registered in some background .net class and prevents the FileStream theresfore from beeing collected. This kind of debugging is something you should overall avoid because it requires some very deep understanding of the .net internals! (but always good for a nice talk ;-) ) – Venson Mar 13 '19 at 22:10
  • 1
    @SLaks - GC doesn't call destructors at all. That's a job for the finalizer thread. – Damien_The_Unbeliever Mar 14 '19 at 06:55
  • @Damien_The_Unbeliever The GC ***thread*** does not but the GC ***system*** in C#, which contains both a GC thread and a finalizer thread, does. – Scott Chamberlain Mar 14 '19 at 07:39
  • But if you're going to pull the finalizer thread into this "GC System", shouldn't you also pull the JIT compiler in because it does work specifically to assist with GC, as an example? Which parts of the CLR aren't in this "GC System"? – Damien_The_Unbeliever Mar 14 '19 at 11:02

2 Answers2

2

FileStream implements IDisposable which means you MUST call Dispose. Please see previous question Do I need to dispose the FileStream object?

MS themselves tell you this https://learn.microsoft.com/en-us/dotnet/api/system.io.filestream?view=netframework-4.7.2

The simplest way is to use a "using" statement

    using (FileStream fs = File.Create(path))
    {
        AddText(fs, "This is some text");
        AddText(fs, "This is some more text,");
        AddText(fs, "\r\nand this is on a new line");
        AddText(fs, "\r\n\r\nThe following is a subset of characters:\r\n");

        for (int i=1;i < 120;i++)
        {
            AddText(fs, Convert.ToChar(i).ToString());

        }
    }
Andrew Harris
  • 1,419
  • 2
  • 17
  • 29
  • 1
    While one *should* call `Dispose` on disposable objects, the OP knows that, and the question is specifically about what happens when it was not done. The Disposable pattern specifically addresses this situation. – GSerg Mar 13 '19 at 21:56
  • 1
    @GSerg not sure I agree that the OP knows that. I read this question as the OP wanting to know why when they dont call the "destructor" the object is hanging onto their file. – Andrew Harris Mar 13 '19 at 22:00
  • I think the point here is still worth making - if you you have an `IDisposable` then you should (if not must) explicitly call `.Dispose()` when you're done with it. – Enigmativity Mar 13 '19 at 23:13
0

As noted in the comments, whenever GC begins to collect it will release the unreachable objects. However to avoid performance issue the GC does not start until one of these conditions happens. It's better not to wait for garbage collector and ourself quickly dispose our unmanaged resources.

Rahmat Anjirabi
  • 868
  • 13
  • 16