Dispose Flashcards

(10 cards)

1
Q

What is the Dispose and main purpose of dispose

A

“The main purpose of Dispose is to free unmanaged resources, like file handles, sockets, or database connections, that the garbage collector doesn’t manage. The GC will eventually release the object’s memory, but not the underlying unmanaged resource. By implementing IDisposable, I can release those resources deterministically, for example via a using block, which also cascades to any disposable objects my class holds.”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What the Garbage Collector (GC) Does

A

The GC only knows how to release managed memory (the memory allocated on the .NET heap).

Example: You create new Customer() → when the object is no longer referenced, GC will eventually reclaim the memory. ✅

But the GC does not know what a file handle, socket, or database connection really means. Those things are outside of .NET’s control — they are OS-level unmanaged resources.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. How .NET Objects Wrap Unmanaged Resources
A

When you use classes like:

FileStream

SqlConnection

Socket

They internally hold handles (like a pointer to a file, database connection, or OS resource). These handles are unmanaged, meaning .NET doesn’t know how to free them automatically.

So what does .NET do?
👉 These classes implement IDisposable, and inside Dispose(), they include explicit instructions to release those unmanaged resources (e.g., CloseHandle, closesocket, sqlite3_close, etc.).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

If You Don’t Call Dispose

A

The object eventually gets garbage collected.

If the class also implements a finalizer (~FileStream()), then when GC runs, it will eventually call that finalizer, which calls the same cleanup logic as Dispose().

But this happens later, and meanwhile you may run out of file handles, sockets, or database connections.

A FileStream object contains an unmanaged file handle.

  • When you call Dispose(), it calls Windows’ API CloseHandle.
  • GC does not do this by itself. It only knows how to free the FileStream object’s managed memory, not how to close the file.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

what happens if there is no dispose no finalizer?

A

If your class holds an unmanaged resource (like a file handle, database connection, or socket) and you don’t implement either Dispose() or a finalizer (~ClassName()), then:

The GC will eventually collect your managed object (the C# class instance).

But the underlying unmanaged resource will not be released, because the GC does not know how to release it.

Result: Resource leak (e.g., file handle stays open, memory from unmanaged heap is never freed, database connection stays locked).

class MyFile
{
private IntPtr fileHandle; // unmanaged resource

public MyFile(string path)
{
    // Open file, store raw OS handle
    fileHandle = OpenFile(path); 
}

// No Dispose
// No Finalizer } ➡️ GC will eventually collect MyFile object, but the fileHandle stays allocated at the OS level. ➡️ The OS thinks the file is still open → process may run out of file handles → "Too many open files" error.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

If there is no dispose but only finalizer.

A

If you implement only a finalizer:

~MyFile()
{
CloseHandle(fileHandle);
}

The OS resource will eventually be released, but only when the GC runs and finalization happens.

This could take a long time (until memory pressure triggers a GC).

Also, finalizers run on a separate thread, so you have less control over when the resource is freed.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

when to implement IDisposable?

A
  1. Classes that wrap unmanaged resources. Without Dispose(), the OS resource would remain open until finalization (which is non-deterministic and can cause memory leaks or file locks).

2- Classes that use managed but scarce/expensive resources

Even if a class doesn’t hold unmanaged resources, it might still need Dispose() to release expensive managed objects deterministically.
Examples:

  • System.Timers.Timer → needs to stop background threads.
  • CancellationTokenSource → needs to release registrations and timers.
  • MemoryStream → managed buffer, but disposing clears internal allocations quickly.

3- Custom application-level classes

Sometimes, you create your own class that manages other IDisposable objects.
Even if your class doesn’t touch unmanaged resources, you should implement IDisposable if it owns other IDisposable objects.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

When would you add a finalizer in your class?

A

Only if your class directly holds unmanaged resources (like a raw OS handle, database connection handle, or unmanaged memory pointer).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What does GC.SuppressFinalize(this) do in Dispose()?

A

: Prevents the finalizer from running since resources are already cleaned, avoiding redundant cleanup and performance overhead.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Implement dispose

A

class MyClass : IDisposable
{
private FileStream file;
private bool disposed = false;

public MyClass()
{
    file = new FileStream("example.txt", FileMode.Open);
}

~MyClass()
{
    Dispose(false); // finalizer: don't touch managed resources
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposed) return;

    if (disposing)
    {
        // ✅ SAFE: Managed objects are still alive
        file?.Close();
    }

    // ✅ Clean unmanaged resources here if any

    disposed = true;
} }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly