Why is the implementation of events in C# not using a weak event pattern by default?
Asked Answered
W

1

24

This question may lead to speculative answers but I presume there's a well thought design decision behind the implementation of event in .

The event pattern in keeps the subscriber alive as long as the publisher of the event is alive. Thus, if you don't unsubscribe, you're leaking memory (well, not really leaking - but memory remains occupied unnecessarily).

If I want to prevent this, I can unsubscribe from events or implement a weak event pattern as proposed at MSDN.

With the event pattern causing so many problems (for beginners?), the question is: why was the decision made that the publisher keeps a strong reference to the subscriber, instead of making them independent or allowing developers to explicitly have a strong or weak modifier?

There are already a couple of questions here about this topic and the answers sound reasonable, but none really answers why it is like it is.

Windflower answered 15/3, 2015 at 18:43 Comment(7)
Because events and Winforms (the main user of evens in the beginning) where introduced in .NET 1.0, in an ancient age, and then they couldn't be modified without breaking everything? If I have to select a feature that would have made .NET a better framework if introduced in 1.0, generics and nullables are the feature.Unasked
Is it really causing so many problems for beginners? Do you have proof or documentation?Ulster
For the most it's a red herring. Events are a messy depency pattern anyway, when you structure there use wisely the leak problem doesn't come up.Ulster
@HenkHolterman No studies but telling from the number of tutorials and questions around the topic here and also generally on the web, I presume it to be a problem.Windflower
"Thus, if you don't unsubscribe, you're leaking memory " - If the subscribee outlives the subscriber. In my experience this is not often the case. I have been bit by this, exactly once before, but that's all.Buchbinder
When you subscribe to an event, why would you not expect to keep getting events until you unsubscribe (or the event publisher is destroyed)?Interstellar
@immibis I'd say it depends. But I can see that the arguments "pro strong reference" weigh more than those for the weak version.Windflower
M
27

One reason certainly is performance. GC handles (which power all of the "exotic" references such as WeakReference) come with a performance cost. Weak events are slower than "strong" events since they require a GC handle. A strong event is implemented (by default) by an instance field storing a delegate. This is just an ordinary managed reference as cheap as any other reference.

Events are supposed to be a very general mechanism. They are not just meant for UI scenarios in which you have maybe a few dozen event handlers. It is not a wise idea to bake a lot of complexity and performance cost into such a basic language feature.

There also is a semantic difference and non-determinism that would be caused by weak references. If you hook up () => LaunchMissiles() to some event you might find the missiles to be launched just sometimes. Other times the GC has already taken away the handler. This could be solved with dependent handles which introduce yet another level of complexity.

Note, that you can implement weak events yourself transparently to the subscriber. Events are like properties in the sense that they are mere metadata and conventions based around the add and remove accessor methods. So this is (just) a question about the defaults that the .NET languages chose. This is not a design question of the CLR.

I personally find it rare that the strong referencing nature of events is a problem. Often, events are hooked up between objects that have the same or very similar lifetime. For example you can hook up events all you want in the context of an HTTP request in ASP.NET because everything will be eligible for collection when the request has ended. Any leaks are bounded in size and short lived.

Memorandum answered 15/3, 2015 at 19:12 Comment(2)
I'm aware that I can implement the weak version myself; I was just wondering why it isn't the default. The missile example makes perfect sense and is a good example why strong references are a good thing to have and were a reasonable decision.Windflower
@krumelur actually, nothing may hold the compiler to use strong refs when it sees anonymous delegate is a subsriber. and as of performance cost, i'm sure those smart guys are able to come up with good decision. actually, some 3rd party solutions are minimizing performance penalty successfully (and also solving "problem" with anonymous delegates).Jone

© 2022 - 2024 — McMap. All rights reserved.