Gravatar of Emran Hussain

Stop Blindly Detaching Event Handlers in .NET (You’re Probably Overdoing It)


There’s a particular kind of paranoia that hits .NET developers at some point in their career.

It usually starts after reading a sentence like this:

“Event handlers can cause memory leaks.”

At first, it sounds like a small warning. But then it grows.

You start looking at your code differently. Every += feels suspicious. Every event subscription feels like a potential bug waiting to happen. And slowly, without even realizing it, you begin writing defensive code everywhere. You detach handlers “just to be safe.” You add cleanup logic even when you don’t fully understand why.

And ironically, that’s where things actually start getting worse, not better.

Because the truth is, most of the time, there was never a problem to begin with.


The Misunderstanding

The issue doesn’t come from events themselves. It comes from a misunderstanding of what they really do.

When you write something like:

publisher.Event += subscriber.Handler;

it looks harmless. Almost declarative. But under the hood, something very specific happens.

The publisher now holds a reference to the subscriber.

That’s it. No mystery beyond that.

And in .NET, references are everything. The garbage collector does not care whether you are “done” with an object. It only cares whether something still holds a reference to it. If a reference exists, the object stays alive. If no references exist, the object can be collected.

So when you subscribe to an event, you’re not just wiring behavior. You’re creating a relationship where one object is effectively saying, “I still need this other object.”


Where the Fear Comes From

Once you understand that, the warning about memory leaks starts to make sense.

If a long-lived object holds a reference to a short-lived object, then the short-lived object may never be collected. It stays in memory longer than intended. Over time, this can build up. That’s what people refer to as an “event handler memory leak.”

And yes, that scenario is real.

But here’s the part that gets lost in most explanations:

That scenario is not the common case.


A Simple Example That Everyone Overthinks

Take a button inside a window. The button raises a Click event, and the window handles it.

There is an event subscription there. Technically, the button holds a reference to the window through that handler.

If you follow the fear-driven logic, you might think you should detach that handler when the window closes.

But pause for a second.

Does it make sense for the window to die before the button?

Of course not. The button exists because the window exists. Their lifetimes are tied together. They come into memory together, and they leave together.

There is no leak here. There never was.

Detaching in this case doesn’t make your code safer. It just makes it noisier.


Where Things Actually Go Wrong

Now consider a slightly different situation.

You have a main window that lives for the entire lifetime of the application. From that window, you open a child window. The child window subscribes to an event from the main window. The user interacts with it for a while, and then closes it.

At this point, you expect the child window to be gone.

But it isn’t.

Because the main window is still alive, and it still holds a reference to the child window through that event subscription. From the garbage collector’s point of view, the child window is still needed.

So it stays.

Not because .NET is broken. Not because GC failed. But because you told the system, very clearly, to keep that object alive.

This is the situation where detaching the event handler actually matters. Not as a precaution, but as a correction of a real lifetime mismatch.


The Only Question That Matters

Once you see both scenarios side by side, the confusion disappears.

You don’t need rules. You don’t need habits. You don’t need to memorize anything.

You only need to ask one question:

Should the subscriber live shorter than the publisher?

If the answer is no, then there is nothing to worry about. Let the relationship exist. Let the code stay clean.

If the answer is yes, then you must detach. Not because “events are dangerous,” but because the relationship you created no longer reflects reality.


Why Over-Detaching Is a Problem

A lot of developers react to this topic by going all in on safety. They detach everything, everywhere, all the time.

But that approach has a cost.

It clutters your code with unnecessary lifecycle management. It makes simple relationships look complicated. It forces future readers to wonder, “Why is this being detached? Is something special going on here?”

And most of the time, the answer is no. Nothing special is going on. The code is just reacting to a fear that was never properly understood.


A More Useful Mental Model

Instead of thinking in terms of “events cause leaks,” it’s much more accurate to think in terms of ownership and lifetime.

An event subscription is not just a callback. It’s a statement about dependency. It says that one object depends on another being alive.

If that statement matches reality, everything works fine.

If that statement is wrong, you get problems.

That’s all there is to it.


Closing Thought

The real issue with event handlers in .NET is not that they are dangerous. It’s that they are often misunderstood.

Most of your event subscriptions are perfectly safe and require no cleanup at all.

A few of them are critical and must be handled carefully.

The difference is not in the syntax. It’s in the relationship between the objects.

Once you start thinking in terms of lifetimes instead of fear, your code becomes simpler, cleaner, and far more intentional.

And you stop fighting problems that were never there in the first place.

Last Modified at Mar 31, 2026
© All content, photographs, graphs and images in this article are copyright protected by SpiceLogic Inc. and may not, without prior written authorization, in whole or in part, be copied, altered, reproduced or published without exclusive permission of its owner. Unauthorized use is prohibited.