<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pc &#187; Software Design</title>
	<atom:link href="http://projectcoho.com/?cat=12&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://projectcoho.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Sun, 22 Jan 2012 01:26:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>WeakAction, or delegates with a weak reference to their target</title>
		<link>http://projectcoho.com/?p=67</link>
		<comments>http://projectcoho.com/?p=67#comments</comments>
		<pubDate>Mon, 11 Apr 2011 02:54:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Code Review]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Contracting]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://www.codeneverwritten.com/2011/04/10/weakaction-or-delegates-with-a-weak-reference-to-their-target/</guid>
		<description><![CDATA[Abstract: Thoughts on implementing an Action-type delegate that holds only a weak reference to the target object. Background I recently started evaluating MVVM libraries for my client’s project. Though I often share parts of my own unpublished library with a &#8230; <a href="http://projectcoho.com/?p=67">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em><font size="2">Abstract: Thoughts on implementing an </font></em><a href="http://msdn.microsoft.com/en-us/library/system.action.aspx" target="_blank"><em><font size="2">Action</font></em></a><em><font size="2">-type delegate that holds only a weak reference to the target object.</font></em></p>
<h3>Background</h3>
<p>I recently started evaluating MVVM libraries for my client’s project. Though I often share parts of my own unpublished library with a client I had inherited this project and it already had it&#8217;s share of commonly-used MVVM types. What it lacked, and I added, was a quickie &quot;message bus&quot; implementation. Not the distributed, enterprise-class sort of message bus, but an intra-app messaging service that decouples senders from receivers. It&#8217;s the message bus that I really wanted to replace with a more robust, tested version that must surely already exist in one of the established MVVM libraries.</p>
<p>As luck would have it the first library I downloaded touted a messaging service but, as is too often the case, you get what you pay for. After perusing the code for a bit I could see that the messaging functionality wasn&#8217;t thread-safe, a feature I require. My app is a multi-threaded WPF app with both managed and native threads and takes pains to keep work off the UI thread in order to achieve smooth and somewhat real-time rendering of data. Wrapping the library’s messaging code for synchronization would be easy, but it doesn&#8217;t feel like fine enough granularity of locking for good performance.</p>
<h3>Weak Action is Weak</h3>
<p>Another driver in looking for an established library is that my quickie message bus implementation holds references to subscribed listeners. Not really a problem unless a listener fails to unsubscribe, in this case the listener will never be garbage collected. I consider that an undesirable situation. So I took a look at the above library&#8217;s implementation of a weak action; I quickly saw that this code used not a weak reference but a strong reference; it suffered the very problem it purported to fix. FYI, I did verify that the problem is known to the library&#8217;s author.</p>
<p>Now, at this time I haven&#8217;t finished evaluating libraries, and this was a bit of a rough start. Maybe I’ll just set aside some time to come up with a solution myself. Like&#8230; now.</p>
<h3>An Elegant Solution (maybe&#8230;)</h3>
<p>The problem I&#8217;d like to solve is that Action holds a reference to the target object of non-static delegates, preventing that target from being GC&#8217;d. The most elegant solution would allow me to simply replace my use of Action and Action&lt;T&gt; with an implementation that holds only a weak reference to the target. And here it is:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 10pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">static</span> Action CreateWeakAction(Action action)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">if</span> (action == <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">&quot;action&quot;</span>);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #008000">// If it's a static delegate there's no need to create a weak reference.</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     <span style="color: #0000ff">if</span> (action.Target == <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>         <span style="color: #0000ff">return</span> action;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>     Type type = action.GetType();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     WeakReference targetRef = <span style="color: #0000ff">new</span> WeakReference(action.Target);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>     MethodInfo method = action.Method;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     <span style="color: #0000ff">return</span> () =&gt;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>         {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>             <span style="color: #008000">// Don't reference 'action' in this lambda expression.</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>             <span style="color: #0000ff">object</span> target = targetRef.Target;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>             <span style="color: #0000ff">if</span> (target == <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>             {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>                 <span style="color: #008000">// Target was GC'd; don't do anything. (Ick.)</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>             }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>             <span style="color: #0000ff">else</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>             {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>                 Delegate.CreateDelegate(type, target, method).DynamicInvoke();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>             }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>         };</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>Using CreateWeakAction is pretty easy:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 10pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> Action action = CreateWeakAction(() =&gt; receiver.DoSomething(42));</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> <span style="color: #008000">// Time passes...</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span> action();</pre>
<p><!--CRLF--></div>
</div>
<p>Now the target (‘receiver’ in the above example) is free to be collected, but I have a new Action delegate returned from CreateWeakAction that will not be collected unless I release my reference to it. More than that, I have no way of telling whether the delegate I&#8217;m holding no longer has a live reference to the target. I could conceivably change my Action to a Func&lt;&gt; that returns an indicator of whether the target was GC&#8217;d, but that would require me to actually call the delegate to determine its state. And I would lose the elegant drop-in replacement I was hoping for.</p>
<h3>A More Measured Solution</h3>
<p>Setting aside my personal desire for elegance solutions, the actual requirements I&#8217;m looking to satisfy in my message bus are twofold: 1) don&#8217;t hold a reference to the target listener and 2) don&#8217;t hold unnecessary objects in the heap. A weak action implementation that satisfies these needs might look something like this:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 10pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">class</span> WeakAction</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">public</span> WeakAction(Action action);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsTargetAlive { get; }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #0000ff">public</span> WeakActionInvocationResult Invoke();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>This would allow me to create an instance of my weak action, invoke it&#8217;s behavior when needed, and check whether the target is still alive so that I can cull stale instances from my message bus implementation. And, thanks to an uninterrupted morning at my local coffee joint I have what I wanted. You may note that I&#8217;ve made an abstraction for invoking instance delegates; this makes that code more easily reusable for generic implementations (e.g., WeakAction&lt;T&gt;).</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 10pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">internal</span> <span style="color: #0000ff">class</span> WeakAction</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> InvocationAgent _instanceAction;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> Action _staticAction;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     <span style="color: #0000ff">public</span> WeakAction(Action action)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>         <span style="color: #0000ff">if</span> (action == <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>             <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">&quot;action&quot;</span>);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>         <span style="color: #0000ff">if</span> (action.Target != <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>         {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>             _instanceAction = <span style="color: #0000ff">new</span> InvocationAgent(action);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>         }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>         <span style="color: #0000ff">else</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>         {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>             _staticAction = action;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>         }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>         Debug.Assert(_instanceAction == <span style="color: #0000ff">null</span> || _staticAction == <span style="color: #0000ff">null</span>);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>         Debug.Assert(!(_instanceAction == <span style="color: #0000ff">null</span> &amp;&amp; _staticAction == <span style="color: #0000ff">null</span>));</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>     <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsTargetAlive { get { <span style="color: #0000ff">return</span> IsStatic || _instanceAction.IsTargetAlive; } }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> IsStatic { get { <span style="color: #0000ff">return</span> _staticAction != <span style="color: #0000ff">null</span>; } }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>     <span style="color: #0000ff">public</span> WeakActionInvocationResult Invoke()</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>     {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>         <span style="color: #0000ff">if</span> (_instanceAction != <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>             <span style="color: #0000ff">return</span> _instanceAction.Invoke();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>         _staticAction();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span>         <span style="color: #0000ff">return</span> WeakActionInvocationResult.Invoked;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35">  35:</span>     }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36">  36:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>Note that I’ve made an optimization for static delegates—there’s no need to incur the cost of dynamic invocation in that case because a static delegate has no target, therefore it won’t prevent anything from being GC’d.</p>
<p>Now imagine we have a messaging implementation that needs to track listeners with Action delegates but would rather not keep a reference to listeners forever if they happen not to unsubscribe. We can now create an instance of WeakAction and use it to invoke the listener&#8217;s Action when we wish; we can also query the WeakAction on occasion to determine whether it still has a live listener.</p>
<p>Finally here are the missing parts to make it work, the interesting bits. What makes this work is pulling apart the delegate into its component parts, holding the target part with a&#160; weak reference, and reassembling the parts into a delegate only when needed to invoke the original delegate. No reference to the original delegate is held.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 10pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">internal</span> <span style="color: #0000ff">enum</span> WeakActionInvocationResult</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     Invoked,</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     Collected,</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span> <span style="color: #0000ff">internal</span> <span style="color: #0000ff">class</span> InvocationAgent</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> Type _type;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> WeakReference _targetRef;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>     <span style="color: #0000ff">private</span> <span style="color: #0000ff">readonly</span> MethodInfo _method;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">public</span> InvocationAgent(Delegate action)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>         Debug.Assert(action.Target != <span style="color: #0000ff">null</span>, <span style="color: #006080">&quot;Expected a non-static delegate&quot;</span>);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>         _type = action.GetType();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>         _targetRef = <span style="color: #0000ff">new</span> WeakReference(action.Target);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span>         _method = action.Method;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20">  20:</span>     }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21">  21:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22">  22:</span>     <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsTargetAlive { get { <span style="color: #0000ff">return</span> _targetRef.IsAlive; } }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23">  23:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24">  24:</span>     <span style="color: #0000ff">public</span> WeakActionInvocationResult Invoke(<span style="color: #0000ff">params</span> <span style="color: #0000ff">object</span>[] args)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25">  25:</span>     {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26">  26:</span>         <span style="color: #0000ff">object</span> target = _targetRef.Target;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27">  27:</span>         <span style="color: #0000ff">if</span> (target == <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28">  28:</span>             <span style="color: #0000ff">return</span> WeakActionInvocationResult.Collected;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29">  29:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30">  30:</span>         <span style="color: #008000">// Don't keep a reference to this delegate.</span></pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31">  31:</span>         Delegate.CreateDelegate(_type, target, _method).DynamicInvoke(args);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32">  32:</span>         <span style="color: #0000ff">return</span> WeakActionInvocationResult.Invoked;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33">  33:</span>     }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34">  34:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>I&#8217;ll leave it as an interesting challenge to the reader to implement WeakAction&lt;T&gt;. Here’s what it might look like:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 10pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">class</span> WeakAction&lt;T&gt;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">public</span> WeakAction(Action&lt;T&gt; action);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsTargetAlive { get; }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>     <span style="color: #0000ff">public</span> WeakActionInvocationResult Invoke(T t);</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 10pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>Grab a cup of coffee and have at it. <img src='http://projectcoho.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Please note: I’ve tested only on the desktop CLR, not Silverlight or Phone, so caveat emptor.</p>
]]></content:encoded>
			<wfw:commentRss>http://projectcoho.com/?feed=rss2&#038;p=67</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where Did My Object Go? Part 2</title>
		<link>http://projectcoho.com/?p=7</link>
		<comments>http://projectcoho.com/?p=7#comments</comments>
		<pubDate>Mon, 03 Dec 2007 20:18:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[CLR]]></category>
		<category><![CDATA[Code Review]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://projectcoho.com/?p=7</guid>
		<description><![CDATA[In Part 1 of this article I discussed the possibility of an object instance being collected before a method returns in this scenario:  new MyObject().LongRunningMethod(); as well as this scenario:  MyObject o = new MyObject(); o.LongRunningMethod(); Here we&#8217;ll discuss how &#8230; <a href="http://projectcoho.com/?p=7">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.codeneverwritten.com/2007/12/where-did-my-object-go-part-1.html" target="_blank">Part 1</a> of this article I discussed the possibility of an object instance being collected before a method returns in this scenario: </p>
<pre class="code">    <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyObject</span>().LongRunningMethod();</pre>
<p>as well as this scenario: </p>
<pre class="code">    <span style="color: #2b91af;">MyObject</span> o = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyObject</span>();    o.LongRunningMethod();</pre>
<p>Here we&#8217;ll discuss how this could become a problem. Frankly, it&#8217;s pretty easy to cause the problem, but I think it generally involves some ugliness on the part of software design or implementation, largely involving clean-up of fields when the instance is finalized. </p>
<h3>Don&#8217;t Try This at Home</h3>
<p>I don&#8217;t think it&#8217;s likely you&#8217;ll see a lot of code that does this, but here&#8217;s one way to run afoul of your object going way: export a reference to a field that the object cleans up when it&#8217;s finalized. You can export the reference, say, by making that field visible through a property. Exposing a field that you&#8217;re going to clean up in the finalizer would be an easy way to create a coupling between your object and other (arbitrary) client code that has no knowledge of your object&#8217;s life span. </p>
<h3>Call Stack Antics</h3>
<p>Another way to invoke the potential problem is to lose your &#8220;this&#8221; reference on the call stack. The code below manages to lose the &#8220;this&#8221; reference by passing a field to the helper method rather than allowing the helper to access the field directly via its own &#8220;this&#8221; reference. When the helper tries to access <span style="font-family: Courier New;">fs.Length</span> an <span style="font-family: Courier New;">ObjectDisposedException</span> is thrown. </p>
<p>Why does this throw? Well, the last live reference to the instance was lost when <span style="font-family: Courier New;">LongRunningMethod</span> passed <span style="font-family: Courier New;">_input</span> to <span style="font-family: Courier New;">Helper</span>. Essentially we&#8217;ve again exported the field value from the instance and no longer hold a reference to the instance, allowing the GC to finalize it. <span style="font-family: Courier New;">Helper</span> is left holding a reference to an object that has been finalized. </p>
<p><a href="http://11011.net/software/vspaste"></a><strong>Note:</strong> Again, you will not see this behavior in a debug build. When running code marked as &#8220;debug&#8221; the JITter <a href="http://blogs.msdn.com/yunjin/archive/2005/05/15/417569.aspx" target="_blank">extends the lifetime</a> of the local object to the end of the method. So you will not see this effect if you&#8217;ve compiled with the /debug flag. </p>
<pre class="code">    <span style="color: #0000ff;">using</span> System;    <span style="color: #0000ff;">using</span> System.IO;

    <span style="color: #008000;">// Ugliness ensues.
</span>    <span style="color: #0000ff;">sealed</span> <span style="color: #0000ff;">class</span> <span style="color: #2b91af;">MyUglyObject
</span>    {
        <span style="color: #0000ff;">public</span> MyUglyObject(<span style="color: #0000ff;">string</span> inputPath)
        {
            <span style="color: #008000;">// Real production code would likely not delete the file when done...
</span>            <span style="color: #008000;">// ...but this is a sample app.
</span>            _input = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">FileStream</span>(<span style="color: #2b91af;">Path</span>.GetTempFileName(), <span style="color: #2b91af;">FileMode</span>.Open, <span style="color: #2b91af;">FileAccess</span>.Read, <span style="color: #2b91af;">FileShare</span>.Read);
        }

        ~MyUglyObject()
        {
            <span style="color: #0000ff;">if</span> (_input != <span style="color: #0000ff;">null</span>)
            {
                _input.Close();
                _input = <span style="color: #0000ff;">null</span>;
            }
        }

        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> LongRunningMethod()
        {
            Helper(_input); <span style="color: #008000;">// Our last reference to 'this' (implicit).
</span>        }

        <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Helper(<span style="color: #2b91af;">FileStream</span> fs)
        {
            <span style="color: #008000;">// A long-running method can easily experience a garbage collection
</span>            <span style="color: #008000;">// before returning. This one happens for force it to occur.
</span>            <span style="color: #2b91af;">GC</span>.Collect();
            <span style="color: #2b91af;">GC</span>.WaitForPendingFinalizers();

            <span style="color: #008000;">// Ka-boom!
</span>            <span style="color: #0000ff;">long</span> inputSize = fs.Length;
            <span style="color: #008000;">// ...
</span>        }

        <span style="color: #0000ff;">private</span> <span style="color: #2b91af;">FileStream</span> _input;
    }

    <span style="color: #0000ff;">class</span> <span style="color: #2b91af;">Program
</span>    {
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span>[] args)
        {
            <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyUglyObject</span>(<span style="color: #a31515;">@"....readme.txt"</span>).LongRunningMethod();
        }
    }</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h3>Can You See It?</h3>
<p>As you can see above it takes a bit of effort to cause the code to blow up. If <span style="font-family: Courier New;">Helper</span> had used <span style="font-family: Courier New;">_input.Length</span> instead of taking a parameter the problem would not exist. </p>
<p>But, what I find a bit creepy about the above code is that if <span style="font-family: Courier New;">Helper</span> were a static method it would seem respectable: </p>
<pre class="code">    <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Helper(<span style="color: #2b91af;">FileStream</span> fs)
    {
        <span style="color: #008000;">// A long-running method can easily experience a garbage collection
</span>        <span style="color: #008000;">// before returning. This one happens for force it to occur.
</span>        <span style="color: #2b91af;">GC</span>.Collect();
        <span style="color: #2b91af;">GC</span>.WaitForPendingFinalizers();

        <span style="color: #008000;">// Ka-boom!
</span>        <span style="color: #0000ff;">long</span> inputSize = fs.Length;
        <span style="color: #008000;">// ...
</span>    }</pre>
<p><a href="http://11011.net/software/vspaste"></a>At first glance it now looks like helper is a normal static helper function, as is likely seen in code bases across the world. It doesn&#8217;t need a &#8220;this&#8221; reference, it takes a reference to the object it uses, everything appears fine on the surface. Would you see the &#8220;this&#8221; reference being lost by the code calling <span style="font-family: Courier New;">Helper</span> in a code review? I&#8217;m not so sure I would have until recently. </p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:5ab9e4f3-aaea-4ce5-83ea-be553bd2b340" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px;">Technorati tags: <a rel="tag" href="http://technorati.com/tags/Coding">Coding</a>, <a rel="tag" href="http://technorati.com/tags/Software%20Design">Software Design</a>, <a rel="tag" href="http://technorati.com/tags/CLR">CLR</a>, <a rel="tag" href="http://technorati.com/tags/C#">C#</a>, <a rel="tag" href="http://technorati.com/tags/Code%20Review">Code Review</a></div>
<div class="blogger-post-footer"><img src="https://blogger.googleusercontent.com/tracker/19212077-4548100263884978316?l=www.codeneverwritten.com" alt="" width="1" height="1" /></div>
]]></content:encoded>
			<wfw:commentRss>http://projectcoho.com/?feed=rss2&#038;p=7</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where Did My Object Go? Part 1</title>
		<link>http://projectcoho.com/?p=8</link>
		<comments>http://projectcoho.com/?p=8#comments</comments>
		<pubDate>Mon, 03 Dec 2007 19:14:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[CLR]]></category>
		<category><![CDATA[Code Review]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://projectcoho.com/?p=8</guid>
		<description><![CDATA[I ran across this scenario a few months ago and was just reminded of it. It takes a bit of an edge case to make it a problem, but it&#8217;s interesting all the same. There&#8217;s a regular idiom in C# &#8230; <a href="http://projectcoho.com/?p=8">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I ran across this scenario a few months ago and was just <a href="http://channel9.msdn.com/ShowPost.aspx?PostID=362232#362232" target="_blank">reminded</a> of it. It takes a bit of an edge case to make it a problem, but it&#8217;s interesting all the same.</p>
<p>There&#8217;s a regular idiom in C# in which we call a method on an object instance that we&#8217;ve created inline:</p>
<pre class="code">    <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyObject</span>().LongRunningMethod();</pre>
<p>There assumption may be an assumption that the lifetime of this instance of <span style="color: #2b91af;"><span style="font-family: Courier New;">MyObject</span></span> extends at least until <span style="font-family: Courier New;">LongRunningMethod</span> returns, but this isn&#8217;t necessarily true. This same assumption is often made about local references to objects:</p>
<pre class="code">    <span style="color: #2b91af;">MyObject</span> o = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyObject</span>();    o.LongRunningMethod();</pre>
<p><a href="http://11011.net/software/vspaste"></a>However, in both these cases the object instance may be collected before <span style="font-family: Courier New;">LongRunningMethod</span> returns.</p>
<h3>Does this really happen?</h3>
<p>Yes, it can and does. The code below exercises this behavior. When you run it you will see the following output, indicating that the object was collected and finalized before <span style="font-family: Courier New;">LongRunningMethod</span> returns:</p>
<p><span style="font-family: Courier New; color: #008000;">    Using release build<br />
</span><span style="font-family: Courier New; color: #008000;">    Inline<br />
    Entering MyObject1.LongRunningMethod().<br />
    Finalizing in ~MyObject1().<br />
    Returning from MyObject1.LongRunningMethod(). </span><span style="font-family: Courier New; color: #008000;">    Local reference<br />
    Entering MyObject1.LongRunningMethod().<br />
    Finalizing in ~MyObject1().<br />
    Returning from MyObject1.LongRunningMethod().</span><strong>Note:</strong> You will not see this behavior in a debug build. When running code marked as &#8220;debug&#8221; the JITter <a href="http://blogs.msdn.com/yunjin/archive/2005/05/15/417569.aspx" target="_blank">extends the lifetime</a> of the local object to the end of the method. So you will <span style="text-decoration: underline;">not</span> see this effect if you&#8217;ve compiled with the /debug flag.</p>
<p>Note also that this article also assumes we&#8217;re using CLR 2.0. Future versions could obviously behavior differently.</p>
<p>Here&#8217;s the code. Just drop it into <span style="font-family: Courier New;">test.cs</span>, run <span style="font-family: Courier New;">csc test.cs</span>, and execute <span style="font-family: Courier New;">test.exe</span>.</p>
<pre class="code">    <span style="color: #0000ff;">using</span> System;

    <span style="color: #0000ff;">sealed</span> <span style="color: #0000ff;">class</span> <span style="color: #2b91af;">MyObject
</span>    {
        ~MyObject()
        {
            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Finalizing in ~MyObject1()."</span>);
        }

        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> LongRunningMethod()
        {
            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Entering MyObject1.LongRunningMethod()."</span>);

            <span style="color: #008000;">// A long-running method can easily experience a garbage collection
</span>            <span style="color: #008000;">// before returning. This one happens for force it to occur.
</span>            <span style="color: #2b91af;">GC</span>.Collect();
            <span style="color: #2b91af;">GC</span>.WaitForPendingFinalizers();

            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Returning from MyObject1.LongRunningMethod()."</span>);
        }
    }

    <span style="color: #0000ff;">class</span> <span style="color: #2b91af;">Program
</span>    {
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span>[] args)
        {
<span style="color: #0000ff;">    #if</span> DEBUG
<span style="color: #808080;">            string build = "debug";
</span><span style="color: #0000ff;">    #else
</span>            <span style="color: #0000ff;">string</span> build = <span style="color: #a31515;">"release"</span>;
<span style="color: #0000ff;">    #endif
</span>            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Using {0} build"</span>, build);

            <span style="color: #008000;">// Try it both ways.

</span>            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Inline"</span>);
            <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyObject</span>().LongRunningMethod();

            <span style="color: #2b91af;">Console</span>.WriteLine();
            <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Local reference"</span>);
            <span style="color: #2b91af;">MyObject</span> o = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">MyObject</span>();
            o.LongRunningMethod();
        }
    }</pre>
<h3>Is this a problem?</h3>
<p>Generally, I&#8217;d say it&#8217;s not a problem. Once it has begun execution, <span style="font-family: Courier New;">LongRunningMethod</span> doesn&#8217;t need the original object reference unless it&#8217;s making reference to that instance. In that case the GC won&#8217;t be able to collect the object.</p>
<p>I&#8217;ll discuss how to make it a problem in <a href="http://www.codeneverwritten.com/2007/12/where-did-my-object-go-part-2.html" target="_blank">Part 2</a> of this article.</p>
<div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:24332e3e-fe71-48b6-a509-a0c9cac22dcd" class="wlWriterSmartContent" style="display: inline; margin: 0px; padding: 0px;">Technorati tags: <a rel="tag" href="http://technorati.com/tags/Coding">Coding</a>, <a rel="tag" href="http://technorati.com/tags/Software%20Design">Software Design</a>, <a rel="tag" href="http://technorati.com/tags/CLR">CLR</a>, <a rel="tag" href="http://technorati.com/tags/C#">C#</a></div>
<div class="blogger-post-footer"><img src="https://blogger.googleusercontent.com/tracker/19212077-7952922260633718206?l=www.codeneverwritten.com" alt="" width="1" height="1" /></div>
]]></content:encoded>
			<wfw:commentRss>http://projectcoho.com/?feed=rss2&#038;p=8</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
