Skip to main content

How to Resolve Error "CS0245: Destructors and object.Finalize cannot be called directly" in C#

The Compiler Error CS0245 is a memory management error. The message reads: "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available."

In C# (unlike C++), you do not manage memory manually. The Garbage Collector (GC) is solely responsible for freeing memory and destroying objects. Because the GC manages the object's lifecycle, it reserves the exclusive right to call the Destructor (syntax ~ClassName) or the underlying Finalize method. Calling these manually would interfere with the GC's internal tracking, potentially causing double-free errors or application crashes.

This guide explains how to correctly implement deterministic cleanup using the IDisposable pattern instead.

Understanding Finalization vs. Disposal

  • Finalization (~Class / Finalize): This is a safety net provided by the runtime. The GC calls this method "eventually" when it decides to reclaim the object's memory. You cannot predict when this happens.
  • Disposal (Dispose): This is a standard pattern (IDisposable interface) for cleaning up resources (like file streams, database connections) immediately when you are done with them.

You cannot force the GC to finalize an object by calling the method directly. If you need to clean up now, you must use Dispose.

Scenario: Attempting to Call Destructors

This error commonly occurs when developers coming from C++ try to explicitly destroy an object using C++ destructor syntax, or when they see the Finalize method in documentation and try to invoke it.

Example of error:

public class FileManager
{
// This is a Destructor (Finalizer)
~FileManager()
{
System.Console.WriteLine("Cleaning up unmanaged resources...");
}
}

public class Program
{
static void Main()
{
FileManager fm = new FileManager();

// ... use fm ...

// ⛔️ Error CS0245: Destructors and object.Finalize cannot be called directly.
// C# does not support calling the destructor syntax directly.
fm.~FileManager();

// ⛔️ Error CS0245: You also cannot call Finalize() directly.
// (Note: Finalize is also protected, so access would fail even before this error).
// fm.Finalize();
}
}

Solution: Implement and Call Dispose

If you want to manually trigger cleanup code, you must implement the IDisposable interface and put your cleanup logic inside the Dispose() method.

Step 1: Implement IDisposable

using System;

public class FileManager : IDisposable
{
// Put your cleanup logic here
public void Dispose()
{
Console.WriteLine("Resources released immediately.");

// Use GC.SuppressFinalize if you also have a destructor
// (to tell the GC it doesn't need to bother calling it).
GC.SuppressFinalize(this);
}
}

Step 2: Call Dispose

Now you can call the method explicitly, or use the using statement which calls it automatically.

public class Program
{
static void Main()
{
// Option A: Explicit Call
FileManager fm = new FileManager();
// ✅ Correct: Calling the public Dispose method
fm.Dispose();

// Option B: Using Statement (Recommended)
// Automatically calls Dispose() at the closing brace.
using (FileManager fm2 = new FileManager())
{
// Use fm2
}
}
}
warning

Do not use Destructors unnecessarily. In modern C#, you rarely need to write a destructor (~Class). You only need one if you are wrapping an Unmanaged Resource (like a raw Windows API handle) and you need to ensure it gets closed even if the user forgets to call Dispose(). For standard database or file operations, standard IDisposable is sufficient.

Conclusion

CS0245 reminds you that the Garbage Collector is in charge of memory.

  1. Don't call ~Method(): This syntax is invalid for calling code in C#.
  2. Don't call Finalize(): This method is for the GC only.
  3. Use Dispose(): If you need to clean up resources at a specific time, implement IDisposable and call .Dispose().