Question: If we include a call to GC.SuppressFinalize(this) in Dispose, is the the call to GC.KeepAlive(this) still required?
Answer: No.
Rationale:
- As has been established, a call to GC.SuppressFinalize anywhere will suppress the finalizer.
- The object must be live at the point GC.SuppressFinalize is called because it must be passed as an argument to that method.
- The call to GC.KeepAlive(this) was only put in Dispose to prevent the finalizer from being invoked while Dispose was still running.
- The GC.KeepAlive(this) call is not necessary because the object will be reachable until its finalizer is suppressed.
Example requiring GC.SuppressFinalize(this)
This is almost identical to the test code used in my last Q&A: “Is a call to GC.KeepAlive(this) required in Dispose?”
Thread 1: CloseHandle starting
Thread 1: Garbage collection in CloseHandle!
Thread 2: Finalizer called
Thread 2: CloseHandle starting
Thread 2: Released handle 0x1
Thread 1: CloseHandle continuing after garbage collection
Thread 1: Released handle 0x1
ReleaseHandle double-released a handle! Bad, bad, bad!
Thread 1: CloseHandle ending
Thread 1: Returning from Main
Thread 2: CloseHandle ending
Thread 1: CloseHandle starting
Thread 1: Garbage collection in CloseHandle!
Thread 2: Finalizer called
Thread 2: CloseHandle starting
Thread 2: Released handle 0x1
Thread 2: CloseHandle ending
Thread 1: CloseHandle continuing after garbage collection
Thread 1: Released handle 0x0
ReleaseHandle released a bad handle! Bad, bad, bad!
Thread 1: CloseHandle ending
Thread 1: Returning from Main
Thread 1: CloseHandle starting
Thread 1: Garbage collection in CloseHandle!
Thread 1: CloseHandle continuing after garbage collection
Thread 1: Released handle 0x1
Thread 1: CloseHandle ending
Thread 1: Returning from Main