0

I tried with the following code

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateNode();

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void ReleaseNode(IntPtr handle);

 class Node
{
    IntPtr nativePtr;
    public int id;
    public Node(int i)
    {
        nativePtr = CreateNode();
        id = i;
        Debug.WriteLine("Constructed " + id);
    }

    ~Node()
    {
        ReleaseNode(nativePtr);
        Debug.WriteLine("Destructed " + id);
    }
}

    class Program
    {
        static void Main(string[] args)
        {

            for (int i = 0; i < 10; i++)
            {
                Node n = new Node(i);
            } //this scope
        }
    }

Each objects for Node class created inside for loop is not destructing after leaving the for loop scope (commented as "this scope"). it is called only when the scope of the Main method ends. is it possible to call the ~Node automatically when the for loop scope ends?

while executing the above code I'm getting the following in the debug window.

Constructed 0
Constructed 1
Constructed 2
Constructed 3
Constructed 4
Constructed 5
Constructed 6
Constructed 7
Constructed 8
Constructed 9
Destructed 9
Destructed 0
Destructed 8
Destructed 7
Destructed 6
Destructed 5
Destructed 4
Destructed 3
Destructed 2
Destructed 1

this shows that the object constructed first is getting destructed at the last. If this happens, what will happen, when im running thousands of items in loop? Will it consume all my memory?

How can i release my unmanaged resources perfectly?

S.Frank Richarrd
  • 488
  • 1
  • 3
  • 15
  • Your title is wrong - all finalizers _are_ being called. Nothing to do here, move along. You should never have to write a ~Finalizer. – bommelding Sep 12 '18 at 06:46
  • After your edit: Wrap the IntPtr in a SafeHandle and implement IDisposable _without_ the ~destructor part. – H H Sep 12 '18 at 16:31
  • @HenkHolterman, safehandle is an abstract class. should i need to implement it in a new class ?? – S.Frank Richarrd Sep 13 '18 at 04:18

3 Answers3

6

TL;DR: Get rid of the finalizer if possible, and just trust the garbage collector to do the right thing.

Finalization is non-deterministic. It's important to understand that objects don't go out of scope; an object doesn't have a scope to start with. Variables go out of scope, and that doesn't trigger anything.

Usually, the garbage collector just runs when it needs to. There is no guarantee about the order in which finalizers will be called, or when they'll be called. (While you can request that the garbage collector runs, that's usually a bad idea and has few guarantees anyway.)

It's almost always a bad idea to have a finalizer in your own classes though: it delays actual garbage collection, and there are almost always better approaches to whatever you'd do in the finalizer.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • If using finalizer is a bad idea, how to release unmanaged resources?? – S.Frank Richarrd Sep 12 '18 at 07:03
  • 1
    @S.FrankRicharrd: Usually it's sufficient to make your type implement `IDisposable`, and rely on callers disposing appropriately. If you've got network connections, files etc as references, *those* should be written appropriately to guard against being left open. If you've got *direct* references to unmanaged resources (via IntPtr etc) then use SafeHandle. See http://joeduffyblog.com/2005/12/27/never-write-a-finalizer-again-well-almost-never/ – Jon Skeet Sep 12 '18 at 07:12
1

C# (and .Net Framework in general) uses Garbage Collector to manage memory, so you shouldn't need to worry about that. If you're coming from c++, this might be feel a little strange at first, but GC does it's job pretty well. Finalizers are called by Garbage Collector and the docs explicitly say:

The programmer has no control over when the finalizer is called because this is determined by the garbage collector.

In case you have a class that is heavy on resources and you want to control when the resources are freed, you should use IDisposable and using statement.

qbik
  • 5,502
  • 2
  • 27
  • 33
-1

Calling the finalizer is done by the garbage collector. To have perfect control over unmanaged resources, use a disposable pattern

class MyResource : IDisposable
{
  ~MyResource()
  {
    Dispose(false);
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this); // don't finalize after the object has already been disposed of
  }

  protected void Dispose(bool disposing)
  {
    if(disposing)
    {
      // TODO: Dispose managed resources
    }

    // TODO: Dispose unmanaged resources
  }
}

// when using
using(var resource = new MyResource())
{
  // ... use resource
} // when out of "using" scope, it will be disposed
ikkentim
  • 1,639
  • 15
  • 30