Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange effect of C# closures on garbage collector

Straight to the code

class Program
{
    private static WeakReference<EventHandler<EventArgs>> _noClosure;
    private static WeakReference<EventHandler<EventArgs>> _closure;

    static void Main(string[] args)
    {
        Init();
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        EventHandler<EventArgs> target;
        Console.WriteLine(_closure.TryGetTarget(out target));
        Console.WriteLine(_noClosure.TryGetTarget(out target));
    }

    class C { public void Go() { } }

    private static void Init()
    {
        _noClosure = new WeakReference<EventHandler<EventArgs>>((sender, args) =>
        {
        });

        var s = new C();
        _closure = new WeakReference<EventHandler<EventArgs>>((sender, args) =>
        {
              s.Go();
        });
    }
}

The output I get from this code is

False
True

How on earth is this possible?

P.S. I came into this while trying to figure out how WeakEventManager works.

like image 412
ironic Avatar asked Jul 08 '16 13:07

ironic


People also ask

Who sings Strange Effect on me?

If the Nine Perfect Strangers theme song sounds familiar, it's probably because this isn't the song's first TV appearance. The track is called "Strange Effect," and is performed by a three-person band that goes by the name Unloved.

Who sings you've got This Strange Effect on me killing Eve?

The song was later revived by Hooverphonic in the '90s. Unloved's cover of the song sees singer Raven Violet joining Unloved and providing the vocals. It boasts a mellow tone, with the words “you've got this strange effect on me, and I like it” repeating. Unloved's take on the song appears in Killing Eve as well.

Who wrote strange effect?

"This Strange Effect" is a song written by Ray Davies of The Kinks, and released first by Dave Berry in July 1965. The single was released in the United States in September 1965.


1 Answers

The compiler will cache the _noClosure delegate in a static field, and reuse it every time you call Init. The exact same instance can be reused every time.

Compare that with _closure, which closes over a new instance of C() on each call to Init() - that can't be cached.

The caching of _noClosure means that there's a strong reference (the field) to the delegate, so it can't be garbage collected.

If you run ildasm on your application, you can see all of this in action.

like image 141
Jon Skeet Avatar answered Sep 20 '22 14:09

Jon Skeet