Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It is a guess, but I tried something like this:</p> <pre><code>public class Foo : IDisposable { private Bar external; private bool disposed; public static Foo CreateFoo() { Foo foo = new Foo(); foo.external = new Bar(); return foo; } private Foo() { } ~Foo() { Console.WriteLine("~Foo"); this.Dispose(false); } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) external.Dispose(); disposed = true; } </code></pre> <p>}</p> <p>That sample will work as you expect. </p> <p>And now my guess:</p> <p>I think that the constructor is not the first method that is called, when an object will be created. It looks like that something out of our control is allocating the space for the created object before constructor is called, or something similar. This is the point where I suppose GC to start working. It is getting the ClassInfo and knows that a finalizer is available. So it starts the Finalizer-Thread and creates a handle to that allocated memory. Know the constructor would be called, and the object would be created from that handle. But before calling a constructor (even a method) something checks for availability of all referenced types within this code block. This is the point where the FileNotFoundException is thrown. Note, that is before you see debugger entering the constructor. Now we move into the Finalizer-Thread, it looks at it's handle of Foo and sees that this handle is not used anymore (actually it was never used). It starts finalizing. This is the point where your finalizer is called. You access the Dispose(bool) method within, and this is the point where the second FileNotFoundException will be thrown, because you are accessing Bar class within that method. That exception will throw on that obscure method check before calling it. I assume that it has something to do with some optimizations, maybe referenced types are lazy loaded.</p> <p>The strange thing, when the constructor won't throw an exception directly, like in my example, the GC will check this and will not call the finalizer for that object. Maybe I'm wrong and the object is still used and not collected by GC.</p> <p><strong>Edit:</strong></p> <p>The best solution would be rather simple. Remove the finalizer from your class. You don't have unmanaged resources in use, so you won't need a finalizer or Dispose(bool) at all.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload