<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3573606178901893990</id><updated>2011-12-03T01:46:21.529-08:00</updated><title type='text'>The Monkey's Grinder</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-289001157383866465</id><published>2010-08-10T06:42:00.000-07:00</published><updated>2010-08-12T12:29:46.550-07:00</updated><title type='text'>Disoriented</title><content type='html'>The Tyranny of Terminology would have us discussing Object Orientation and Functional Programming, calling our code by its Patterns and Paradigms. I am going to plead ignorance of these epistemologies and just show you some&amp;nbsp;C#. Feel free to know for yourself what it Really Means.&lt;br /&gt;&lt;br /&gt;Code like this was written for Mono.Upnp. Expect news there soon.&lt;br /&gt;&lt;br /&gt;Our story begins here:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;abstract class&lt;/span&gt; &lt;span class="Apple-style-span" style="color: #38761d;"&gt;ContentDirectory&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;"ContentDirectory" is UPnP parlance for a directory of content. (See the &lt;a href="http://www.upnp.org/specs/av/UPnP-av-ContentDirectory-v1-Service.pdf"&gt;ContentDirectory:1 service template PDF&lt;/a&gt;. Or better still, don't.) The CD is a hierarchy of objects. Objects have descriptive class names like &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;"object.item.audioItem.musicTrack"&lt;/span&gt;&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #990000;"&gt;"object.container.systemFolder"&lt;/span&gt;&lt;/span&gt;. That gives you some idea, yes?&lt;br /&gt;&lt;br /&gt;The CD has methods like &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Browse&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Search&lt;/span&gt;. Here is the signature for &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Search&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt; Search (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt; containerId,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt; searchCriteria,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt; startIndex,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt; requestCount,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;out&lt;/span&gt; &lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt; numberedReturned,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;out&lt;/span&gt; &lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt; totalMatches)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I will pause to explain the return value: it is a string of XML describing the result set.&lt;br /&gt;&lt;br /&gt;Now, in a source file not far away...&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;class&lt;/span&gt; &lt;span class="Apple-style-span" style="color: #38761d;"&gt;InMemoryContentDirectory&lt;/span&gt; : &lt;span class="Apple-style-span" style="color: #38761d;"&gt;ContentDirectory&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It may not shock you to learn that an&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;InMemoryContentDirectory&lt;/span&gt;&lt;/span&gt; keeps an in-memory collection of its object hierarchy. It has a method called &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GetChildren&lt;/span&gt;. Here is the signature:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;IEnumerable&amp;lt;CDObject&amp;gt;&lt;/span&gt; GetChildren (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt; containerId)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Explanatory&amp;nbsp;pause #2: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;CDObject&lt;/span&gt;&lt;/span&gt; is short for "Content Directory Object"; it is the root type of objects in the CD.&lt;br /&gt;&lt;br /&gt;If you were me, then this is how you would implement&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;InMemoryContentDirectory&lt;/span&gt;.Search&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;totalMatches = 0;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;var&lt;/span&gt; results = &lt;span class="Apple-style-span" style="color: #0b5394;"&gt;new&lt;/span&gt; &lt;span class="Apple-style-span" style="color: #38761d;"&gt;List&amp;lt;CDObject&amp;gt;&lt;/span&gt; (requestCount);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;foreach&lt;/span&gt; (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;var&lt;/span&gt; child &lt;span class="Apple-style-span" style="color: #0b5394;"&gt;in&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;GetChildren (containerId)) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (IsMatch (child, searchCriteria)) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;totalMatches++;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (totalMatches &amp;gt; startIndex &amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results.Count &amp;lt; requestCount)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results.Add (child);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;numberReturned = results.Count;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;return&lt;/span&gt; Serialize (results);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I may or may not have promised a theory-free post — I don't really remember now — but in any event, this is standard Object Oriented Programing fare. To state the obvious:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: #f4cccc;"&gt;You create a list to hold the results.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: #f4cccc;"&gt;You iterate through the children of the subject container.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;For each match, you increment &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;totalMatches&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;If you have not reached the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;startIndex&lt;/span&gt;, you keep going.&lt;/li&gt;&lt;li&gt;Otherwise unless you have reached the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;requestCount&lt;/span&gt;, you add the matching object to the results list.&lt;/li&gt;&lt;li&gt;You return the serialized results list.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="background-color: #f4cccc;"&gt;Which iterates through the list&lt;/span&gt; and serializes each object to XML, returning the whole XML string.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;I have highlighted the problems with your solution in salmon. You are allocating a new &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;List&amp;lt;CDObject&amp;gt;&lt;/span&gt;&lt;/span&gt; to hold objects which already exist in a collection somewhere. Also, you are iterating through the results twice: first in your pass through the container's children and then again to serialize them.&lt;br /&gt;&lt;br /&gt;If you were still me then this just won't do. LINQ should come to mind but have I got a fun surprise for you: Mono.Upnp targets the .NET 2.0 profile. So how might you Query the Language without fancy INtegration?&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;IEnumerable&amp;lt;CDObject&amp;gt;&lt;/span&gt; Search (&lt;br /&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&lt;/span&gt; containerId,&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&lt;/span&gt; searchCriteria,&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&lt;/span&gt; startIndex,&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&lt;/span&gt; requestCount)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt; count = 0;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach&lt;/span&gt; (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;var&lt;/span&gt; child &lt;span class="Apple-style-span" style="color: #0b5394;"&gt;in&lt;/span&gt; GetChildren (containerId)) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (IsMatch (child, searchCriteria)) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count++;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (count &amp;gt; startIndex &amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count - startIndex &amp;lt; requestCount)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;yield return&lt;/span&gt; child;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt;&amp;nbsp;Search (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt;&amp;nbsp;containerId,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt;&amp;nbsp;searchCriteria,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;startIndex,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;requestCount,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;out&lt;/span&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;numberedReturned,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;out&lt;/span&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;totalMatches)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt; serializer = &lt;span class="Apple-style-span" style="color: #0b5394;"&gt;new&lt;/span&gt; Serializer ();&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt; results = Search (&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;containerId, searchCriteria,&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;startIndex, requestCount);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt; xml = serializer.Serialize (results);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberReturned = serializer.NumberReturned;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;totalMatches = 0;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;/span&gt; xml;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;/ul&gt;No more &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;List&amp;lt;CDObject&amp;gt;&lt;/span&gt;&lt;/span&gt; and we only iterate through the results once (during &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;Serializer&lt;/span&gt;.Serialize&lt;/span&gt;). The serializer counts the results for us during its iteration and exposes &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;Serializer&lt;/span&gt;.&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;NumberReturned&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;There is one big problem: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;totalMatches&lt;/span&gt; will always be 0. We know what the correct value should be (it is the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;count&lt;/span&gt; variable in our generator), but we have no way to get it out: generator methods cannot have by-reference parameters (a.k.a. "out" parameters).&lt;br /&gt;&lt;br /&gt;To make this solution work, we could return something fancier than plain old &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;IEnumerable&amp;lt;CDObject&amp;gt;&lt;/span&gt;&lt;/span&gt; which would expose &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;count&lt;/span&gt; through a property; let's call it&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;TotalMatchesCount&lt;/span&gt;. But we could not use generators; we would have to implement &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;IEnumerator&amp;lt;CDObject&amp;gt;&lt;/span&gt;&lt;/span&gt; by hand just like'n Ye Olde Days.&lt;br /&gt;&lt;br /&gt;A final caveat:&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;TotalMatchesCount&lt;/span&gt;&amp;nbsp;would only have the correct value &lt;i&gt;after&lt;/i&gt;&amp;nbsp;we iterate through the results in &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;Serializer&lt;/span&gt;.Serialize&lt;/span&gt;, just as with &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;Serializer&lt;/span&gt;.NumberReturned&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This approach frankly sucks. Alright you/me, show me your teeth!&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;abstract&lt;/span&gt; &lt;span class="Apple-style-span" style="color: #38761d;"&gt;void&lt;/span&gt; VisitChildren (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt; containerId,&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;Action&amp;lt;CDObject&amp;gt;&lt;/span&gt; visitor);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt;&amp;nbsp;Search (&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt;&amp;nbsp;containerId,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;string&lt;/span&gt;&amp;nbsp;searchCriteria,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;startIndex,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;requestCount,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;out&lt;/span&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;numberedReturned,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;out&lt;/span&gt;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;int&lt;/span&gt;&amp;nbsp;totalMatches)&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt;&amp;nbsp;total =&amp;nbsp;&lt;span class="Apple-style-span" style="color: #990000;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt;&amp;nbsp;count =&amp;nbsp;&lt;span class="Apple-style-span" style="color: #990000;"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&lt;/span&gt;&amp;nbsp;serializer = new Serializer ();&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;VisitChildren (containerId, child =&amp;gt; {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (IsMatch (child, searchCriteria) {&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total++;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/span&gt; (total &amp;gt; startingIndex &amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count &amp;lt; requestCount)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;serializer.OnResult (child);&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count++;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;numberReturned = count;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;totalMatches = total;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #0b5394;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;/span&gt; serializer.OnDone ();&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;No more &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;IEnumerable&amp;lt;CDObject&amp;gt;&lt;/span&gt; GetChildren&lt;/span&gt;, and the implementation lives in the abstract &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-style-span" style="color: #38761d;"&gt;ContentDirectory&lt;/span&gt;&lt;/span&gt; class where it works with any sort of subclass: in-memory, db-backed, web service, &amp;amp;c.&lt;br /&gt;&lt;br /&gt;As an exercise I want you to invent a name for this pattern which rhymes with neither "shmisitor" nor "shmobserver." Bonus points for double entendres. Then I want you to imagine a world without return values. Get back to me when your mind is blown.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-289001157383866465?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/289001157383866465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=289001157383866465' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/289001157383866465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/289001157383866465'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2010/08/tyranny-of-terminology-would-have-us.html' title='Disoriented'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-724562724490868621</id><published>2009-07-28T20:06:00.000-07:00</published><updated>2009-07-28T20:34:44.434-07:00</updated><title type='text'>Mono.Upnp Dance Party</title><content type='html'>So it's &lt;a href="http://themonkeysgrinder.blogspot.com/2008/10/monoupnp-bun-in-oven.html"&gt;been a while&lt;/a&gt; since mention was made of a certain &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;UPnP&lt;/span&gt; library. What happened? First, I had various other things to do. Second, I decided to do two or three major &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;refactorings&lt;/span&gt;, ditching a lot of code. Third, I moved development to &lt;a href="https://github.com/lunchtimemama/Mono.Upnp/tree"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;github&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;What the status?&lt;/span&gt;&lt;br /&gt;The status? &lt;span style="font-style: italic;"&gt;The status&lt;/span&gt;, you ask?! THIS is the status! If you can't see, I am pointing at my TV. My TV which is connected to my PS3. My PS3 which is &lt;span style="font-style: italic;"&gt;playing music from my laptop computer with WIRELESS NETWORKING!&lt;/span&gt; Yes friends, tonight at last, Mono.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Upnp&lt;/span&gt; and the PS3 are doing the DANCE OF LOVE. I plug, it plays. Universally. About ten minutes ago I finally tracked down the typo responsible for a day's worth of debugging and let me tell you, &lt;a href="http://www.last.fm/music/Starfucker"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Starfucker&lt;/span&gt;&lt;/a&gt; never sounded so good (and they already sound so good anyway, seriously, you should listen to them).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;What now?&lt;/span&gt;&lt;br /&gt;I've kept pretty quite about the whole project because I wanted to lay all the groundwork before make too much noise. There is still work to be done on the core of the library, but now that it's working I'll start sharing more frequent updates. You can follow the project on &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;github&lt;/span&gt; if you want commit-by-commit news.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Can I help?&lt;/span&gt;&lt;br /&gt;Sure! But helping might be a little tricky. The solution only loads in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;MonoDevelop&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;SVN&lt;/span&gt;, and there are certain necessary &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;BCL&lt;/span&gt; fixes that require Mono from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;SVN&lt;/span&gt; too (one of them isn't even committed yet). It's not quite "checkout, compile, run," but if you're interested in helping out, I will be more than happy to get you up to speed. I wrote a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;TODO&lt;/span&gt; on the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;github&lt;/span&gt; wiki today with some stuff that needs doing. Testing is also something I will need help on. I don't have access to an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;XBox&lt;/span&gt; 360 anymore, so I'm going to need help on that front. As the library and the tools evolve, we'll need to test with as many devices as we can.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Yeah!&lt;/span&gt;&lt;br /&gt;Yeah indeed! NOW DANCE!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-724562724490868621?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/724562724490868621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=724562724490868621' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/724562724490868621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/724562724490868621'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/07/monoupnp-dance-party.html' title='Mono.Upnp Dance Party'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-5209573273471495252</id><published>2009-07-23T18:03:00.000-07:00</published><updated>2009-11-08T00:24:37.116-08:00</updated><title type='text'>C#er</title><content type='html'>Was chillin' with the impish &lt;a href="http://abock.org/"&gt;abock&lt;/a&gt; last weekend when, all of a hullabaloo, he geniused something wonderful.&lt;br /&gt;&lt;br /&gt;"Behold!" he cried:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;var button = new Button {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Label = "Push Me",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Relief = ReliefStyle.None&lt;br /&gt;};&lt;br /&gt;button.Clicked += (o, a) =&amp;gt; Console.WriteLine ("ouch!');&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;To which I replied, "?"&lt;br /&gt;&lt;br /&gt;"Watch..." said he:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;var button = new Button {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Label = "Push Me",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Relief = ReliefStyle.None,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Clicked +=&amp;gt; Console.WriteLine ("ouch!")&lt;br /&gt;};&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;"?!" came my response.&lt;br /&gt;&lt;br /&gt;"Is not it better?"&lt;br /&gt;&lt;br /&gt;"Yes," quoth I, "but gentle abock, this wundercode... it doth not compile!"&lt;br /&gt;&lt;br /&gt;"... YET!"&lt;br /&gt;&lt;br /&gt;Well friends, yet is over. I am here today to tell you that yes, IT DOTH COMPILE. This is what you get when Scott forgets to pull the git repos for his real projects before a plane flight: unsolicited language features. And there are other goodies:&lt;br /&gt;&lt;br /&gt;As with anonymous methods via the delegate keyword, you may omit the parameters to a lambda if you aren't going to use them. This is also helpful when the delegate type has no parameters. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;Func&amp;lt;string&amp;gt; myFunc = () =&amp;gt; "blarg";&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Just look at those parenthesis! Chillin' there all higgledy piggledy. They look like some unseemly ASCII art. But now, presto chango:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;Func&amp;lt;string&amp;gt; myFunc =&amp;gt; "blarg";&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;See what I did there? That's called an assignment arrow. It is better. Don't argue with me, because you're wrong.&lt;br /&gt;&lt;br /&gt;For my next trick, you can do the same kind of thing with lambdas and event handler registration.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;myButton.Clicked +=&amp;gt; Console.WriteLine ("higgledy piggledy");&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Because who ever uses the EventHandler arguments? A big, fat nobody, that's who.&lt;br /&gt;&lt;br /&gt;Last but not least, you can now do all of this plus regular event handler registration inside of object initializers. abocks around the world rejoice!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;There Is No Syntax Without Corner Cases&lt;/h3&gt;&lt;br /&gt;So there &lt;em&gt;is&lt;/em&gt; at least one possible ambiguity with this new syntax:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;class Foo {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Add (Action&amp;lt;string&amp;gt; action) { ... }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Action&amp;lt;string&amp;gt; Bar { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Meanwhile, in some unsuspecting method:&lt;br /&gt;var foo = new Foo {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Bar =&amp;gt; Console.WriteLine ("HELP ME!")&lt;br /&gt;};&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Question:&lt;/b&gt; Is that an object initialization, or a collection initialization?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Answer:&lt;/b&gt; It's ambiguous.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution:&lt;/b&gt; It's an object initialization. If you want it to be a collection initialization, throw some parenthesis around "Bar." This would be a good candidate for a compiler warning. And if you want to make it an unambiguous object initialization, you could do:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier;"&gt;var foo = new Foo {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Bar = () =&amp;gt; Console.WriteLine (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"What does this ASCII art even mean?") &lt;br /&gt;};&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Patch&lt;/h3&gt;&lt;br /&gt;The patch for all of this is available &lt;a href="http://getbanshee.org/~abock/stoms-super-spectacular-abock-inspired-csharp-revolutionizing-gmcs-patch.diff"&gt;here&lt;/a&gt;. Apply to mcs, recompile, then use gmcs.exe passing -langversion:future.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Future&lt;/h3&gt;&lt;br /&gt;There has been on-again-off-again talk about adding non-standard language features to the C# compiler under the guard of -langversion:future. The main concern voiced is the ability to maintain such extensions. I will definitely discuss this patch with &lt;a href="http://mareksafar.blogspot.com/"&gt;Marek&lt;/a&gt; and co. to see about landing it in mainline. I'll keep you up to date.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Are You Bock Enough?&lt;/h3&gt;&lt;br /&gt;In the meantime, I call upon manly man Aaron Bockover to make the only manly choice available: fork C# and ship the compiler. Because you're not really a serious media player until you have your own special language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-5209573273471495252?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/5209573273471495252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=5209573273471495252' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/5209573273471495252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/5209573273471495252'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/07/cer.html' title='C#er'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-7029415348536730753</id><published>2009-07-16T22:25:00.000-07:00</published><updated>2009-07-17T07:57:02.336-07:00</updated><title type='text'>Casting Call</title><content type='html'>Type safety only gets you so far; eventually you have to cast. There are three features in the C# language which address typing: the unary cast operator and the binary "as" and "is" operators. I see people misuse these operators all the time, so here for your records are the official Best Ways to use each.&lt;br /&gt;&lt;br /&gt;If you want to check the type of an object and do not care about using the object as that type, use the "is" operator. For example:&lt;br /&gt;&lt;br /&gt;if (thing is MyType) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do something which doesn't involve thing&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;If you want to check the type of an object and then use that object as that type, use the "as" operator and the check for null. For example:&lt;br /&gt;&lt;br /&gt;var my_type_thing = thing as MyType;&lt;br /&gt;if (my_type_thing != null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do something with my_type_thing&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;This only works for reference types since value types cannot be null. For value types, use the "is" and cast operators. For example:&lt;br /&gt;&lt;br /&gt;if (thing is MyValueType) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var my_value_type_thing = (MyValueType)thing;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do something with my_value_type_thing&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;If you know for a fact that an object is some type, use the cast operator. For example:&lt;br /&gt;&lt;br /&gt;var my_type_thing = (MyType)thing;&lt;br /&gt;// do something with my_type_thing&lt;br /&gt;&lt;br /&gt;These patterns minimize the operations performed by the runtime. This wisdom comes by way &lt;a href="http://mareksafar.blogspot.com/"&gt;Marek&lt;/a&gt; who educated me on this a while ago. Please pass it on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-7029415348536730753?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/7029415348536730753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=7029415348536730753' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/7029415348536730753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/7029415348536730753'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/07/casting-call.html' title='Casting Call'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-7424651513360195501</id><published>2009-07-09T11:32:00.000-07:00</published><updated>2009-07-09T14:27:56.474-07:00</updated><title type='text'>Dear LazyMarket</title><content type='html'>Are you hiring? Do you know someone who is hiring? Well you're in luck! Because none other than yours truly is looking for a job. If you're interested in how great I am, send an email to lunchtimemama@gmail.com and I'll get you a copy of my resume. I look forward to hearing from you...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-7424651513360195501?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/7424651513360195501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=7424651513360195501' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/7424651513360195501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/7424651513360195501'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/07/dear-lazymarket.html' title='Dear LazyMarket'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-8862156145792846035</id><published>2009-06-30T23:23:00.000-07:00</published><updated>2009-06-30T23:51:39.236-07:00</updated><title type='text'>Variance, Thy Name is Ambiguity</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold; font-style: italic;font-size:130%;" &gt;Previously&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;On This Blog...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;"I love you, Generic Variance, and I want your babies &lt;a href="http://themonkeysgrinder.blogspot.com/2009/02/c-4-is-now.html"&gt;RIGHT NOW!&lt;/a&gt;"&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;"I think there's &lt;a href="http://themonkeysgrinder.blogspot.com/2009/04/whos-afraid-of-generic-variance.html"&gt;&lt;span style="font-style: italic;"&gt;something you should know&lt;/span&gt;&lt;/a&gt; about Generic Variance..."&lt;br /&gt;&lt;br /&gt;"&lt;a href="http://themonkeysgrinder.blogspot.com/2009/05/further-generic-variance-thoughts.html"&gt;I can change him!&lt;/a&gt;"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold; font-style: italic;font-size:130%;" &gt;And now, the thrilling continuation...&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;I've just sent my recommendation to the ECMA 335 committee regarding the generic variance problem. I present it here for your reading pleasure:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Quick Recap&lt;/h3&gt;&lt;br /&gt;The following is an example of an ambiguous circumstance involving generic variance, the very sort over which we have all lost so much sleep:&lt;br /&gt;&lt;br /&gt;.class interface abstract I&amp;lt;+T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method public abstract virtual instance !T Foo ()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.class A {}&lt;br /&gt;.class B extends A {}&lt;br /&gt;.class C extends A {}&lt;br /&gt;&lt;br /&gt;.class X implements I&amp;lt;class B&amp;gt;, I&amp;lt;class C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class B I[B].Foo () { .override I&amp;lt;class B&amp;gt;::Foo }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class C I[C].Foo () { .override I&amp;lt;class C&amp;gt;::Foo }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Meanwhile, in some unsuspecting method...&lt;br /&gt;I&amp;lt;A&amp;gt; i = new X ();&lt;br /&gt;A a = i.Foo (); // AMBIGUITY!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Give a Runtime A Bone&lt;/h3&gt;&lt;br /&gt;To disambiguate such situations, we introduce a new custom attribute in the BCL. For the sake of example, let's call it System.PreferredImplementationAttribute. The PreferredImplementationAttribute is applied to a type and indicates which implementation should be selected by the runtime to resolve variance ambiguities. Our above definition of the type X would now look like this:&lt;br /&gt;&lt;br /&gt;.class X implements I&amp;lt;class B&amp;gt;, I&amp;lt;class C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .custom instance void System.PreferredImplementationAttribute::.ctor (class System.Type) = { type(I&amp;lt;class C&amp;gt;) }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class B I[B].Foo () { .override I&amp;lt;class B&amp;gt;::Foo }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class C I[C].Foo () { .override I&amp;lt;class C&amp;gt;::Foo }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;New Rules&lt;/h3&gt;&lt;br /&gt;With the addition of this attribute, the runtime requires that any type defined in an assembly targeting the 335 5th edition runtime which implements multiple interfaces that are variants of a common generic interface MUST specify ONE AND ONLY ONE PerferredImplementationAttribute for EACH of the potentially ambiguous common interfaces, and that each such specification of a PerferredImplementationAttribute must reference an interface implemented by the type that is a legal variant of the ambiguous common interface. In other words, all possible ambiguities MUST be disambiguated by the use of PreferredImplementationAttribute custom attributes. If a type does not satisfy these rules, the runtime MUST throw a System.TypeLoadException.&lt;br /&gt;&lt;br /&gt;As this rule only applies to assemblies targeting the new version of the runtime, old images will continue to execute without issue. If the committee prefers, the resolution of ambiguities in old types may remain unspecified, or alphabetical priority could be codified in the spec to standardize such behavior. I would be fine leaving it unspecified.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Custom Attributes vs. Metadata&lt;/h3&gt;&lt;br /&gt;Ideally, I feel disambiguation information belongs in the type metadata structure rather than a custom attribute. If the committee feels that amending the metadata specification is tenable, I would recommend doing so (though I don't have any thoughts at this time on the exact logical or physical nature of such an amendment). If, on the other hand, changing the metadata spec at this point in the game is not feasible, then a custom attribute will just have to do. I see the addition of one custom attribute type to the Base Class Library as entirely justified.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;An Aside to Our Friends on the 334 Committee&lt;/h3&gt;&lt;br /&gt;As a note to language designers targeting the runtime, I personally would consider it obnoxious if developers where burdened with the manual application of such a custom attribute. C# and other languages would do well to prohibit the direct use of the custom attribute, favoring instead a special syntax to denote the preferred implementation (the "default" keyword comes to mind in the case of C#). If this committee changes the type metadata spec to include preferred implementation information (and does not introduce a custom attribute type for that purpose), then special language syntaxes will be necessary.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;An Alternative&lt;/h3&gt;&lt;br /&gt;In the interest of completeness, I will describe an alternate (if similar) approach to the ambiguity resolution problem. Rather than annotate types to indicate which of their interface implementations will satisfy ambiguous calls, the preferred implementation could be denoted on a per-member basis. Referring again to our original type X, this solution would modify that type thusly:&lt;br /&gt;&lt;br /&gt;.class X implements I&amp;lt;class B&amp;gt;, I&amp;lt;class C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class B I[B].Foo () { .override I&amp;lt;class B&amp;gt;::Foo }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class C I[C].Foo () {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;.override I&amp;lt;class C&amp;gt;::Foo&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;.custom instance void System.PreferredImplementationAttribute::.ctor ()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The member I[C].Foo is annotated with the System.PreferredImplementationAttribute, indicating that it will be selected by the runtime to fulfill otherwise ambiguous calls to I&amp;lt;T&amp;gt;.Foo. Note that in this solution the constructor to the PerferredImplementationAttribute type is parameterless. The runtime ensures that for EACH of the members of an interface which is the common variant of two or more of the interfaces implemented by a type, ONE AND ONLY ONE of the implementations for that member is flagged as "preferred."&lt;br /&gt;&lt;br /&gt;Per-member preference definition affords developers more control but costs runtime implementers time, effort, and simplicity. I also don't envision many scenarios when developers would desire per-member control over implementation preference. I personally find this approach less tasteful than the per-interface solution but I mention it here, as I said, for completeness.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;One More Thing...&lt;/h3&gt;&lt;br /&gt;There remains a situation on which there are varied opinions:&lt;br /&gt;&lt;br /&gt;.class interface abstract I&amp;lt;+T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method public abstract virtual instance !T Foo ()&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.class A {}&lt;br /&gt;.class B extends A {}&lt;br /&gt;&lt;br /&gt;.class X implements I&amp;lt;class A&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class A I[A].Foo () { .override I&amp;lt;class A&amp;gt;::Foo }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.class Y extends X implements I&amp;lt;class B&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method virtual instance class B I[B].Foo () { .override I&amp;lt;class B&amp;gt;::Foo }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Meanwhile, in some unsuspecting method...&lt;br /&gt;I&amp;lt;A&amp;gt; i = new Y ();&lt;br /&gt;A a = i.Foo ();&lt;br /&gt;&lt;br /&gt;In this situation I&amp;lt;A&amp;gt;::Foo is called on an object of type Y. There is an implementation of I&amp;lt;A&amp;gt;::Foo in Y's type hierarchy (X::I[A].Foo), but there is also an available implementation which is a legal variant of I&amp;lt;A&amp;gt; in Y itself (Y:I[B].Foo). Does the runtime favor the exact implementation, or the more derived variant implementation? I don't have strong feelings on the matter, but my slight preference is for favoring the exact implementation.&lt;br /&gt;&lt;br /&gt;The runtime is deciding on behalf of the developer which implementation is most appropriate. It could be argued that an exact implementation, wherever it is to be found the type hierarchy, is more appropriate than a variant implementation.&lt;br /&gt;&lt;br /&gt;Also - and this is an implementation detail which should not outweigh other considerations but may be useful to keep in mind if all other things are equal - Mono stores a type's implemented interfaces in a binary tree, meaning that finding an exact implementation is an O(log n) worst-case operation, whereas finding a legal variant interface among a type's implemented interfaces is an O(n) worst-case operation (all interfaces must be examined to see if a legal variant exists among them). I haven't heard of any way to do O(log n) (or better) lookup of variants. With such popular types as IEnumerable`1 becoming variant, the superior time complexity could make a difference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-8862156145792846035?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/8862156145792846035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=8862156145792846035' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/8862156145792846035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/8862156145792846035'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/06/variance-thy-name-is-ambiguity.html' title='Variance, Thy Name is Ambiguity'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-5157848960396864872</id><published>2009-05-16T12:52:00.000-07:00</published><updated>2009-05-17T09:39:22.096-07:00</updated><title type='text'>Further Generic Variance Thoughts</title><content type='html'>I was writing a type today that implements both IDictionary&amp;lt;TKey, TValue&amp;gt; and ICollection&amp;lt;TValue&amp;gt;. These interfaces require the implementation of both IEnumerable&amp;lt;TValue&amp;gt; and IEnumerable&amp;lt;KeyValuePair&amp;lt;TKey, TValue&amp;gt;&amp;gt;. In .NET 4, the IEnumerable&amp;lt;T&amp;gt; type will be covariant. This exposes my type to potential ambiguity if it is assigned to a location of type IEnumerable&amp;lt;object&amp;gt; (see the &lt;a href="http://themonkeysgrinder.blogspot.com/2009/04/whos-afraid-of-generic-variance.html"&gt;previous post&lt;/a&gt; for details). If I were to follow my own advice and forbid the implementation of multiple interfaces which are variants of a single common interface, this type would be illegal. So on further reflection, I have decided to amend my opinion thusly: If there are multiple interface implementations which are variants of a common interface, then there must be implicit implementations of all of the potentially ambiguous members. These public members are then selected by the runtime to satisfy otherwise ambiguous calls. The implicit member implementations need not all be for the same interface. For example, if we have some interface IFoo&amp;lt;out T&amp;gt; with members T Bar(); and T Bat(); and we have some type with implements both IFoo&amp;lt;string&amp;gt; and IFoo&amp;lt;Uri&amp;gt;, it could have the members public string Bar(){} and public Uri Bat(){}. Any call to IFoo&amp;lt;object&amp;gt;.Bar() on an object of this type will execute the IFoo&amp;lt;string&amp;gt; implementation, and IFoo&amp;lt;object&amp;gt;.Bat() will execute the Uri implementation.&lt;br /&gt;&lt;br /&gt;I believe that this restriction should be enforced at least at the language level (for all variant-capable languages targeting .NET), if not at the runtime level: all potentially ambiguous members &lt;em&gt;must&lt;/em&gt; have public implementations. This resolves the ambiguity in a logical way, allows for more complex type design (which, as in the case of my type today, is desirable), and gives developers the ability to control which implementation will be selected. I think it is a Good Thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-5157848960396864872?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/5157848960396864872/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=5157848960396864872' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/5157848960396864872'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/5157848960396864872'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/05/further-generic-variance-thoughts.html' title='Further Generic Variance Thoughts'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-5312314216485953757</id><published>2009-04-09T14:18:00.000-07:00</published><updated>2009-05-06T14:35:44.707-07:00</updated><title type='text'>Who's Afraid of Generic Variance?</title><content type='html'>&lt;h3&gt;Abstract&lt;/h3&gt;&lt;br /&gt;This post is an in-depth exploration of generic variance in the ECMA 335 standard and the REALLY BIG PROBLEM therewith. See the &lt;a title="read up" href="http://themonkeysgrinder.blogspot.com/2009/02/c-4-is-now.html" id="bdfp"&gt;previous post&lt;/a&gt; on generic variance for an introduction to the topic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Punchline&lt;/h3&gt;&lt;br /&gt;The ECMA 335 Standard, 4th Edition, allows for &lt;i&gt;nondeterministic&lt;/i&gt; &lt;i&gt;execution&lt;/i&gt;. This means that in certain situations involving generic variance, the specification does not provide sufficient guidance to resolve ambiguities. As you may imagine, nondeterminism is a Very Bad Thing in computing (&lt;a href="http://en.wikipedia.org/wiki/Nondeterministic_programming" id="p4mn" title="usually"&gt;usually&lt;/a&gt;). It means that your program may run one way on .NET 3.5 and another way on .NET 4 and a third way if Richard Stallman saw his shadow in the morning.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Solution&lt;/h3&gt;&lt;br /&gt;The ECMA 335 committee is hoping to resolve this problem in the 5th edition. Unfortunately, no clear solutions have revealed themselves. There are a number of possible approaches, all of which have pros and cons. I will be describing the problems and their possible solutions in this post. Feel free to weigh in on the matter. A robust discussion will aid the 335 group in their decision.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Implementation Selection Problem&lt;/h3&gt;&lt;br /&gt;There are a number of increasingly pointy corner cases, all variations on the same theme: which of multiple implementation does the runtime select for execution? I will describe these corner cases in order of ascending pointiness. For each case, I will propose a deterministic solution and then demonstrate how that solution fails to address the next corner case. (Note: the deterministic solutions I propose are merely examples. Other solutions could be used.) &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Overview&lt;/h3&gt;&lt;br /&gt;Before getting into the corner cases, I will provide a broad overview of the problem. Ambiguous situations arise when there are multiple implementations of one generic interface (with different type arguments). The generic interface must have some variant generic type parameter.&lt;br /&gt;&lt;h4&gt;Vocab&lt;/h4&gt;The &lt;i&gt;implemented types&lt;/i&gt; are the closed generic interface types that are actually implemented in the type hierarchy of the object in question.&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;execution type&lt;/i&gt; is the closed generic interface type of the location to which the object is assigned. Calls made to members of this type must be resolved to an implementation among the implemented types.&lt;br /&gt;&lt;br /&gt;An &lt;i&gt;exact implementation&lt;/i&gt; is the implementation of an implemented type whose generic type arguments precisely match those of the execution type. For example, if type A implements the generic interface I&amp;lt;String&amp;gt;, and we assign some A to an I&amp;lt;String&amp;gt; location, then its implementation for that interface is exact.&lt;br /&gt;&lt;br /&gt;A &lt;i&gt;variant implementation&lt;/i&gt; is the implementation of an implemented type whose generic type arguments do not precisely match those of the execution type, but are legal variants thereof. For example, if type A implements the covariant generic interface I&amp;lt;String&amp;gt;, and we assign some A to an I&amp;lt;Object&amp;gt; location, then its implementation for that interface is variant.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Case 0&lt;/h3&gt;&lt;h4&gt;Nothing to See Here&lt;/h4&gt;As a starting point, let us consider the following non-variant scenario which is NOT ambiguous.&lt;br /&gt;&lt;div style="font-family: Courier;"&gt;&lt;br /&gt;interface I&amp;lt;T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;A&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A I&amp;lt;A&amp;gt;.Next() {...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Y : X, I&amp;lt;A&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A I&amp;lt;A&amp;gt;.Next() {...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;br /&gt;I&amp;lt;A&amp;gt; i = new Y();&lt;br /&gt;A someA = i.Next();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;There are two implementations of I&amp;lt;A&amp;gt;: one in X and one in Y. Which is used for the call to I&amp;lt;A&amp;gt;.Next()?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;The implementation in type Y is used. As I said, this is not actually a problematic situation. I illustrate this case to demonstrate one of the ways the spec currently resolves potential ambiguities. In this case, the implementation in the most derived class is used. Y is more derived than X, therefore its implementation is used.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Case 1&lt;/h3&gt;&lt;h4&gt;Easy Pickins&lt;/h4&gt;&lt;div style="font-family: Courier;"&gt;interface I&amp;lt;out T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;A&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A I&amp;lt;A&amp;gt;.Next() {...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Y : X, I&amp;lt;B&amp;gt; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; B I&amp;lt;B&amp;gt;.Next() {...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;br /&gt;I&amp;lt;A&amp;gt; i = new Y();&lt;br /&gt;A someA = i.Next();&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;There are two implementations which suffice for I&amp;lt;A&amp;gt;: the I&amp;lt;A&amp;gt; exact implementation in X, and the I&amp;lt;B&amp;gt; variant implementation in Y. Which does the runtime select?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;There are two possible solutions. We could adopt the aforementioned "most derived implementation wins" rule, in which case the runtime would pick the variant implementation in Y.&lt;br /&gt;&lt;br /&gt;The other solution is to favor exact implementations over variant implementations, in which case the runtime would pick the exact but less derived implementation in X.&lt;br /&gt;&lt;br /&gt;For the sake of argument, let's adopt the second solution: the runtime will select the most-derived exact implementation if one exists.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Case 2&lt;/h3&gt;&lt;h4&gt;The Decider&lt;/h4&gt;&lt;div style="font-family: Courier;"&gt;interface I&amp;lt;out T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class C : B {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;B&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; B I&amp;lt;B&amp;gt;.Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Y : I&amp;lt;C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C I&amp;lt;C&amp;gt;.Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;br /&gt;I&amp;lt;A&amp;gt; i = new Y();&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;There is no exact implementation of I&amp;lt;A&amp;gt;. There are two variant implementations: I&amp;lt;B&amp;gt; in X and I&amp;lt;C&amp;gt; in Y. Which does the runtime select?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;As before, there are two options. We could choose the most derived implementation, in which case the runtime would select the I&amp;lt;C&amp;gt; implementation in Y.&lt;br /&gt;&lt;br /&gt;The other option is to select the variant implementation with the least "distance" to the execution type. We are attempting to select an implementation for I&amp;lt;A&amp;gt;. We have variant implementations I&amp;lt;B&amp;gt; and I&amp;lt;C&amp;gt;. B is nearer to A in the inheritance chain than is C. Therefore we say that I&amp;lt;B&amp;gt; has less "distance" to I&amp;lt;A&amp;gt; than does I&amp;lt;C&amp;gt;. It may therefore be the case that the I&amp;lt;B&amp;gt; implementation is a more relevant substitute for I&amp;lt;A&amp;gt; since B is nearer to A than is C. By this rule, we would select the less distant but less derived I&amp;lt;B&amp;gt; implementation in X.&lt;br /&gt;&lt;br /&gt;There are problems with the second option. What if there are multiple type parameters, each with different distances? How do we calculate the total distance of the type? Such a solution could require a rather complex set of rules, complicating the specification and compliant runtimes. And at the end of the day, it is dubious whether "distance" is a meaningful selection criteria.&lt;br /&gt;&lt;br /&gt;For the sake of argument, let us go with the first option: the runtime will select the most derived variant implementation in the absence of an exact implementation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Case 3&lt;/h3&gt;&lt;h4&gt;Ambiguity is Scary&lt;/h4&gt;&lt;div style="font-family: Courier;"&gt;interface I&amp;lt;out T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class C : B {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;B&amp;gt;, I&amp;lt;C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; B I&amp;lt;B&amp;gt;.Next () {...}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C I&amp;lt;C&amp;gt;.Next() {...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;br /&gt;I&amp;lt;A&amp;gt; i = new X();&lt;br /&gt;A someA = i.Next();&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;There is no exact implementation for I&amp;lt;A&amp;gt; and there are two variant implementations, I&amp;lt;B&amp;gt; and I&amp;lt;C&amp;gt;, both defined in the same type: X. Which does the runtime select?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;We are now approaching the point at which any selection rule is largely arbitrary. We can revisit the "least distant" option though its problems are no fewer. It is also unclear whether such a selection behavior is obvious to the user. The user may not have taken "distance" into consideration when designing their types. On the other hand, the user who wrote this code clearly failed to take a number of things into consideration and it's now the runtime's job to make the best possible choice. Anything is better than nondeterminism.&lt;br /&gt;&lt;br /&gt; For the sake of argument, let us say that we select the variant implementation with the least distant type argument. If there are multiple type parameters, we take the distance from the first non-identical set of arguments.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Case 4&lt;/h3&gt;&lt;h4&gt;Sophie's Choice&lt;/h4&gt;&lt;div style="font-family: Courier;"&gt;interface I&amp;lt;out T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class C : A {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;B&amp;gt;, I&amp;lt;C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; B I&amp;lt;B&amp;gt;.Next() {...}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C I&amp;lt;C&amp;gt;.Next() {...}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;br /&gt;I&amp;lt;A&amp;gt; i = new X();&lt;br /&gt;A someA = i.Next();&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;br /&gt;There is no exact implementation of I&amp;lt;A&amp;gt;. There are two variant implementations: I&amp;lt;B&amp;gt; and I&amp;lt;C&amp;gt;, both defined in type X. B and C are equidistant from A. What would Jesus do?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;Select I&amp;lt;B&amp;gt;. Because B comes before C in the alphabet.&lt;br /&gt;&lt;br /&gt;If you think that's heinously arbitrary, you're right! But remember our motto: anything is better than nondeterminism.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;[UPDATE]&lt;/b&gt;&lt;br /&gt;Several people have proposed selecting based on the order in which the implementations appear in the code. This would select I&amp;lt;B&amp;gt; because it is defined first. As I said, my solutions are merely example rules.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Recap&lt;/h3&gt;&lt;br /&gt;To review, our selection rules are: &lt;br /&gt;&lt;ol&gt;&lt;li&gt;The most derived exact implementation wins&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Failing an exact implementation, the most derived variant implementation wins&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If there are multiple equally-derived variant implementations and no exact implementation, the implementation with the least "distance" wins. If there are multiple type parameters, the distance is taken from the first non-identical set of arguments.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If there are multiple equally-derived equidistant variant implementations and no exact implementation, the implementation with alphabetical priority wins. If there are multiple type parameters, the alphabetical priority is taken from the first non-identical set of arguments.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How Arbitrary Is Too Arbitrary?&lt;/h3&gt;&lt;br /&gt;As the cases get cornerier, the solutions get arbitrarier. Somewhere around case 3, the arbitrariness begins to offend the delicate sensibilities. There are alternatives to arbitrary selection which I will describe in a moment but I would like to first emphasize the virtue of arbitrariness: it is better than nondeterminism. ANYTHING is better than nondeterminism. Eeny meeny miny moe is a step up from the current spec. If no other solution can be decided upon, egregious arbitrariness is still better than what we have.&lt;br /&gt;&lt;br /&gt;As we consider alternatives to arbitrary selection, consider the question, "how arbitrary is too arbitrary?" For which of the above cases is one of the below alternatives a superior option? Bear it in mind as we press ahead...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Exceptions&lt;/h3&gt;&lt;br /&gt;Runtime exceptions are an alternative to arbitrary implementation selection. If an ambiguous situation arises, an exception pops up. The benefit of exceptions is that they let the developer know that there is an ambiguous situation, whereas arbitrary selection may simply lead to unexpected and difficult-to-debug behavior. There are two exceptional approaches:&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Exception On Call&lt;/h4&gt;When an ambiguous call is made, throw a runtime exception. For example:&lt;br /&gt;&lt;div style="font-family: Courier;"&gt;&lt;br /&gt;interface I&amp;lt;out T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class C : A {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;B&amp;gt;, I&amp;lt;C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; B I&amp;lt;B&amp;gt;.Next();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C I&amp;lt;C&amp;gt;.Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;/span&gt;&lt;br style="font-family: Courier New;"&gt;&lt;br /&gt;I&amp;lt;A&amp;gt; i = new X();&lt;br /&gt;A someA = i.Next(); // AMBIGUOUS CALL EXCEPTION HAPPENS HERE&lt;/div&gt;&lt;br /&gt;This has the benefit of only throwing an exception if the ambiguity is actually going to be a problem. The major issue is, exceptions can be thrown from innocent code. If you pass an X to some library function which takes an I&amp;lt;A&amp;gt;, that library will blissfully call I&amp;lt;A&amp;gt;.Next() and trigger the exception. The stack trace will implicate the library, but the culprit is the X type definition.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Exception On Assignment&lt;/h4&gt;When an object is assigned to an ambiguous interface, throw a runtime exception. For example:&lt;br /&gt;&lt;div style="font-family: Courier;"&gt;&lt;br /&gt;interface I&amp;lt;out T&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class C : A {}&lt;br /&gt;&lt;br /&gt;class X : I&amp;lt;B&amp;gt;, I&amp;lt;C&amp;gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; B I&amp;lt;B&amp;gt;.Next();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C I&amp;lt;C&amp;gt;.Next();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test code&lt;br /&gt;I&amp;lt;A&amp;gt; i = new X(); // AMBIGUOUS ASSIGNMENT EXCEPTION HAPPENS HERE&lt;br /&gt;A someA = i.Next();&lt;/div&gt;&lt;br /&gt;This approach runs the risk of unnecessary exceptions. If an ambiguous call is never made, an ambiguous assignment is not dangerous. This approach also allows exceptions to be thrown from innocent code. If some library takes an I&amp;lt;B&amp;gt;, an X can be passed without ambiguity. The library is then at liberty to assign the I&amp;lt;B&amp;gt; to an I&amp;lt;A&amp;gt;, resulting in an exception. The library is not at fault, but the stack trace implies otherwise.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Invalid Ambiguity&lt;/h3&gt;&lt;br /&gt;Once you have answered the question "how arbitrary is too arbitrary," take everything on the "too arbitrary" side of the fence and make it against the rules. For example, if you conclude that there is no reasonable way of selecting between two variant implementations defined in the same type, then it would be invalid to define a type which implements multiple interfaces that are variants of a common interface.&lt;br /&gt;&lt;br /&gt;This has the downside of invaliding currently valid CLI images. I don't know to what degree forward compatibility is a goal for the ECMA 335 spec.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Language-Level Enforcement&lt;/h3&gt;&lt;br /&gt;Irrespective of the runtime's solution to this problem, languages can impose independent restrictions on ambiguous type design. For example, C# could make it a compilation error for a type to implement multiple interfaces that are variants of a common interface, even if such a type is valid for the runtime. If all major languages enforce unambiguous type design, the pressure on the runtime to avoid arbitrariness is lessened since the dangerously arbitrary rules will not affect any code written in a major language. The only people vulnerable to the arbitrary rules are ostensibly savvy enough to be trusted with understanding obscure runtime behaviors.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Least Worst Solution&lt;/h3&gt;&lt;br /&gt;There is clearly no silver bullet for the problem. The least worst solution will be a blend of several approaches. The appropriate blend will depend upon a number of things such as the importance of the forward compatibility of CLI images. The ultimate solution must address two concerns: the elimination of nondeterminism and the prevention of developer confusion. The same implementation must deterministically execute every time, and it must be clear to developers which implementation that will be.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My Thoughts&lt;/h3&gt;&lt;br /&gt;The implementation selections rules should begin as follows:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The most derived exact implementation wins.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In the absence of an exact implementation, the most derived variant implementation wins.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Situations not addressed by these rules are considered "ambiguous."&lt;br /&gt;&lt;br /&gt;As a solution to ambiguous situations, exceptions serve neither of the stated goals. They achieve deterministic failure rather than deterministic execution and their stack traces obfuscate the root of the problem. A sufficiently descriptive error message could aid developer comprehension but it would be far too easy for a stack trace from "someone else's code" to become a bug report to the wrong people or an ignored problem. I think exceptions are the worst worst solution.&lt;br /&gt;&lt;br /&gt;Language-level ambiguity preclusion is an very good idea but adding a compiler error for ambiguous type design could break existing code when existing interfaces are made variant. For example, consider this C#:&lt;br /&gt;&lt;div style="font-family: Courier;"&gt;&lt;br /&gt;class A {}&lt;br /&gt;&lt;br /&gt;class B : A {}&lt;br /&gt;&lt;br /&gt;class C : A {}&lt;br /&gt;&lt;br /&gt;class X : IEnumerable&amp;lt;B&amp;gt;, IEnumerable&amp;lt;C&amp;gt; {...}&lt;/div&gt;&lt;br /&gt;This is currently a legal C# class definition. However with the release of .NET 4 the IEnumerable&amp;lt;T&amp;gt; interface will be made covariant, making the above class vulnerable to ambiguity. Making ambiguous type design a warning rather than an error would solve this problem but I think it is worth breaking existing code in the interest of drawing developers' attention to the new ambiguity.&lt;br /&gt;&lt;br /&gt;All variance-capable .NET languages should add errors for ambiguous type design.&lt;br /&gt;&lt;br /&gt;Which brings us to the question of the runtime's ambiguity handling mechanism. The two best options are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Make ambiguities illegal.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add an arbitrary implementation selection rule: alphabetical priority of type arguments.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Option 1 achieves both objectives of a solution: it guarantees deterministic execution and ensures developer comprehension by proscribing ambiguous circumstances altogether. However it also breaks the forward compatibility of existing binaries.&lt;br /&gt;&lt;br /&gt;Option 2 guarantees deterministic execution but does not serve developer comprehension (no developer wants to consider the alphabetical priority of type arguments when designing their types). In conjunction with language-level enforcement, however, no developer should ever suffer this confusion. And this option affords all currently valid CLI images continued validity.&lt;br /&gt;&lt;br /&gt;So the key question is, how important is compatibility?&lt;br /&gt;&lt;br /&gt;I am tending toward option 1, but I think there is room for debate.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What Do You Think?&lt;/h3&gt;&lt;br /&gt;Comment away.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Next Time...&lt;/h3&gt;&lt;br /&gt;If all that weren't enough, there is a problem with variancifying existing types (such as turning IEnumerable&amp;lt;T&amp;gt; into IEnumerable&amp;lt;out T&amp;gt;) but I will save that for another post.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Thanks&lt;/h3&gt;&lt;br /&gt;Thanks goes to Dr. Nigel Perry on the ECMA 334 and 335 standards committee for working with me on this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-5312314216485953757?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/5312314216485953757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=5312314216485953757' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/5312314216485953757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/5312314216485953757'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/04/whos-afraid-of-generic-variance.html' title='Who&apos;s Afraid of Generic Variance?'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-3854228814046254747</id><published>2009-04-04T20:36:00.000-07:00</published><updated>2009-04-05T02:34:24.182-07:00</updated><title type='text'>Exceptional APIs</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Axioms for public API design:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Axiom 1&lt;/span&gt;&lt;br /&gt;NullReferenceExceptions that come out of your code ARE YOUR FAULT!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Axiom 2&lt;/span&gt;&lt;br /&gt;The fewer exceptions your code can possibly throw, the better!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Applications of these axioms:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's say we're writing a public API, you and I. In it, let's say we have the following awesome method:&lt;br /&gt;&lt;blockquote style="font-family:courier;"&gt;public void Foo(string s) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Bar(s.Length);&lt;br /&gt;}&lt;/blockquote&gt;You will notice that we dereference s to get its Length property. If some misguided user of ours were to pass null to Foo, an NRE would pop out of our code like an overweight stripper out of a wedding cake. Awkward! And then the stack trace would get passed all over school and all the kids would laugh at us.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Lemma 1&lt;/span&gt;&lt;br /&gt;From axiom 1 it follows: Null-check EVERYTHING YOU DEREFERENCE unless you know where it came from.&lt;br /&gt;&lt;br /&gt;We could do a conditional dereference:&lt;br /&gt;&lt;blockquote style="font-family:courier;"&gt;public void Foo(string s) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (s != null) Bar(s.Length);&lt;br /&gt;}&lt;/blockquote&gt;Or we could verify the argument:&lt;br /&gt;&lt;blockquote style="font-family:courier;"&gt;public void Foo(string s) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (s == null) throw new ArgumentNullException("s");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Bar(s.Length);&lt;br /&gt;}&lt;/blockquote&gt;If our method absolutely needs to dereference the object in order to do its job, then argument verification is the way to go. This may seem like trading one exception type for another, but it's really not. Argument exception types are perfectly acceptable - they inform our misguided user what went wrong and how to make it right. On the other hand, NREs mean that we didn't verify the argument or null-check before dereferencing. And they mean that all the kids will laugh at us.&lt;br /&gt;&lt;br /&gt;Let's say that we decide on argument verification. Now let's say that we want to add a convenience overload:&lt;br /&gt;&lt;blockquote style="font-family:courier;"&gt;public void Foo() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo("");&lt;br /&gt;}&lt;/blockquote&gt;Looks good, right? WRONG!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Lemma 2&lt;/span&gt;&lt;br /&gt;From axiom 2 it follows: Use 'null' as a sentinel between overloads for the default value when null is not an otherwise permissible value.&lt;br /&gt;&lt;br /&gt;My favorite non-fiction book of all time, Framework Design Guidelines, specifically says not to do this. It is wrong. Well, sort of. FDG advises against using null as a "magic" sentinel, period. I argue that sentinel null is correct for parameters which are omitted in convenience overloads. Here is why:&lt;br /&gt;&lt;br /&gt;To recap, our API currently looks like this:&lt;br /&gt;&lt;blockquote style="font-family:courier;"&gt;public void Foo() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo("");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Foo(string s) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (s == null) throw new ArgumentNullException("s");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Bar(s.Length);&lt;br /&gt;}&lt;/blockquote&gt;Let's consider the possible ways our misguided user can use this API. If he or she calls the convenience overload, or passes a string literal, everything's honkey dorey:&lt;br /&gt;&lt;span style="font-family:courier;"&gt;Foo(); // This is fine&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier;"&gt;Foo("How the hell do I use this API?"); // This too is just fine&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But if misguided user passes null to Foo(string), or passes a variable which &lt;span style="font-style: italic;"&gt;may&lt;/span&gt; be null, things aren't so rosey:&lt;br /&gt;&lt;span style="font-family:courier;"&gt;Foo(null); // Exception city!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier;"&gt;Foo(someString); // It depends...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;How is our misguided user to know what is and is not a safe call? They could look at our documentation. Assuming we wrote any. And assuming we correctly documented all of the parameters which need to be non-null. Or they could test passing null and see if it throws.&lt;br /&gt;&lt;br /&gt;(As a side note, I wonder all the time about whether I can pass null to an API. Documentation is usually no help and if I see a parameterless overload, I generally assume that I can)&lt;br /&gt;&lt;br /&gt;More likely, they will do none of the above and just write something resembling the last example call, passing a variable. A variable which is usually not null. A variable which is never null during testing. But a variable which, when released into the wild may, under some unforeseen circumstance, be null. Then all the kids would cry.&lt;br /&gt;&lt;br /&gt;The solution:&lt;br /&gt;&lt;blockquote style="font-family:courier;"&gt;public void Foo() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo(null);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Foo(string s) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (s == null) s = "";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Bar(s.Length);&lt;br /&gt;}&lt;/blockquote&gt;All possible inputs to this API are valid and there is zero change of an exception. &lt;span style="font-style: italic;"&gt;This is better!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some may complain about semantics purity or somesuch. They are wrong.&lt;br /&gt;&lt;br /&gt;So, if you have some public API which takes a parameter that a) is not allowed to be null, and b) has a default value for the purpose of convenience overloads, use the sentinel null. Just do it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-3854228814046254747?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/3854228814046254747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=3854228814046254747' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/3854228814046254747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/3854228814046254747'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/04/exceptional-apis.html' title='Exceptional APIs'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-9040359307008873221</id><published>2009-02-22T00:14:00.000-08:00</published><updated>2009-02-22T04:03:30.421-08:00</updated><title type='text'>Now Is The Winter of Our Optional and Named Parameters</title><content type='html'>Optional and named method parameters are coming to C# 4. This means you can provide default values for method parameters. When you call the method, you can name only the parameters you want to specify - default values will be used for all other parameters.&lt;br /&gt;&lt;h4&gt;Here's how you use it:&lt;/h4&gt;&lt;div style="font-family: courier new;"&gt;public void Foo (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int doodad = 1,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string humdinger = "",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string wuchacallit = "STELLAAAA!")&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Do stuff here&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void Test ()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo ();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (humdinger = "Beard Lust");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (doodad = 5,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wuchacallit = "SHAMU!");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (wuchacallit = "Kia",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;humdinger = "Ora",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doodad = 42);&lt;br /&gt;}&lt;/div&gt;&lt;h4&gt;Here's how it &lt;em&gt;really&lt;/em&gt; works:&lt;/h4&gt;&lt;div style="font-family: courier new;"&gt;public void Foo (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Optional, DefaultParameterValue(1)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int doodad,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Optional, DefaultParameterValue("")]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string humdinger,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Optional, DefaultParameterValue("STELLAAAA!")]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string wuchacallit)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Do stuff here&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void Test ()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (1, "", "STELLAAAA!");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (1, "Beard Lust", "STELLAAAA!");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (5, "", "SHAMU!");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (42, "Ora", "Kia");&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The compiler just sprinkles the default values into every callsite. There are a few problems with this approach. Let's suppose I release version 1 of my awesome library with the above Foo method. You compile. All is well. Now let's say I release version 2 of my library, in which the default value "STELLAAAA!" is changed to "KHAAAAN!". But your code still has the old default value baked in. You need to re-compile your code to get the new default value. There is also the problem that injecting the full argument list into every callsite bloats the size of the code. Bigger code means more to JIT and fewer cache hits&lt;br /&gt;&lt;h4&gt;How it &lt;em&gt;should&lt;/em&gt; work:&lt;/h4&gt;&lt;div style="font-family: courier new;"&gt;struct FooSettings {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int doodad_value = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string humdinger_value = "";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string wuchacallit_value = "STELLAAAA!";&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public int doodad {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get { return doodad_value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set { doodad_value = value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public string humdinger {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get { return humdinger_value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set { humdinger_value = value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public string wuchacallit {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;get { return wuchacallit_value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set { wuchacallit_value = value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Foo (FooSettings settings)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Do stuff&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void Test ()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (new FooSettings ());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (new FooSettings { humdinger = "Beard Lust" });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (new FooSettings {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doodad = 5,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wuchacallit = "SHAMU!" });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Foo (new FooSettings {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wuchacallit = "Kia",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;humdinger = "Ora",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doodad = 42 });&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Thanks to C# 3's object initialization, you can squint at the call and almost see the named parameter syntax (just ignore "new FooSettings"). This pattern of using a special "settings" type for passing arguments to methods already exists in the framework (see XmlReader.Create and XmlWriter.Create for an example). I am proposing that the compiler auto-generate these types and provide full optional/named parameter sugar. The compiler-generated types would be publicly nested within the type containing the method and named "[MemberName]Settings" by default.&lt;br /&gt;&lt;br /&gt;This is better than callsite default value injection because:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It versions well&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It adds a fixed amount of additional code (the type), whereas injection adds more code every time you use it&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It is CLS compliant&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This is how C# 4 should do optional and named parameters.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-9040359307008873221?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/9040359307008873221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=9040359307008873221' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/9040359307008873221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/9040359307008873221'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/02/now-is-winter-of-our-optional-and-name.html' title='Now Is The Winter of Our Optional and Named Parameters'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-4184131956615753119</id><published>2009-02-14T00:50:00.000-08:00</published><updated>2009-02-14T01:15:13.332-08:00</updated><title type='text'>Generic Type Parameters AS Method Parameters</title><content type='html'>I have long had an interest in method contracts (pre- and post-conditions). I followed Spec# and I continue to follow the Pex project. I am also a big fan of doing argument verification at the highest possible level of a public API. I was working on a public API today which takes a Type object. My method looked like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier new;"&gt;public string GetClassName (Type type) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (type == null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArugmentNullException ("type");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!type.IsSubclassOf (typeof (UpnpObject)) &amp;amp;&amp;amp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type != typeof (UpnpObject)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ArgumentException (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"The type does not derive from UpnpObject.",&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"type");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do stuff with 'type'&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It then occurred to me that I can do the same thing with a generic type parameter, but get all the checks for free!&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: courier new;"&gt;public string GetClassName&amp;lt;T&amp;gt; () where T : UpnpObject {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//do stuff with 'typeof (T)'&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Tada! Using generic type parameters as method parameters is nothing new (Aaron has something like this in the Banshee service stack), but the really neat thing is that you can use the generic constraints as a kind of argument pre-condition. If you have a method which takes a Type, consider using a generic type parameter rather than a method parameter. It guarantees that 'null' cannot be passed and it allows you to specify ancestry, interfaces, ref/value types, and the presence of a default constructor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-4184131956615753119?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/4184131956615753119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=4184131956615753119' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/4184131956615753119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/4184131956615753119'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/02/generic-type-parameters-as-method.html' title='Generic Type Parameters AS Method Parameters'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-207754177809403426</id><published>2009-02-03T20:22:00.000-08:00</published><updated>2009-02-03T21:27:27.529-08:00</updated><title type='text'>C# 4 is NOW!</title><content type='html'>&lt;span style="font-weight: bold;"&gt;WHAT?&lt;/span&gt;&lt;br /&gt;Generic type variance support just landed in mcs. This is a C# 4 language feature.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;WHERE?&lt;/span&gt;&lt;br /&gt;You can give it a go by checking out SVN trunk and compiling your variant code with gmcs -langversion:future.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;REALLY?&lt;/span&gt;&lt;br /&gt;Well, this adds compiler support for variance but the Mono VM isn't up to speed on its variance handling. This means that you can compile the code but it won't actually run on Mono (until we fix that, which I am also doing). You &lt;span style="font-style: italic;"&gt;can&lt;/span&gt; run it on the .NET 2.0 VM.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;WHAT THE HELL ARE YOU TALKING ABOUT?&lt;/span&gt;&lt;br /&gt;Generic type variance is like this:&lt;br /&gt;&lt;br /&gt;Let's say I have some IEnumerable&amp;lt;string&amp;gt;, like so:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;blockquote&gt;IEnumerable&amp;lt;string&amp;gt; myStrings = GetSomeStrings ();&lt;/blockquote&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now let's say I have some other method which takes an IEnumerable&amp;lt;object&amp;gt;, like so:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: courier new;"&gt;void DoStuff (IEnumerable&amp;lt;object&amp;gt; someObjects)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach (object o in someObjects) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do some stuff with each object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;POP QUIZ: Can I pass myStrings to DoStuff in C# 3? Strings are objects, right? And IEnumerable&amp;lt;T&amp;gt; is just a way of getting Ts. So if strings are objects, and IEnumerable&amp;lt;string&amp;gt; just returns strings, then we can also say that it returns objects. Just like IEnumerable&amp;lt;object&amp;gt;. So it &lt;span style="font-style: italic;"&gt;should work&lt;/span&gt;, right?&lt;br /&gt;&lt;br /&gt;ANSWER: Negatorz!&lt;br /&gt;&lt;br /&gt;This is a problem of generic type variance. There are two kinds of variance: covariance and contravariance. The above example is covarant, meaning that you want to &lt;span style="font-style:italic;"&gt;broaden&lt;/span&gt; the type of an &lt;span style="font-style:italic;"&gt;output&lt;/span&gt;. Contravariance is the opposite: &lt;span style="font-style:italic;"&gt;narrowing&lt;/span&gt; the type of an &lt;span style="font-style:italic;"&gt;input&lt;/span&gt;. Let's consider a delegate:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: courier new;"&gt;delegate void Handler&amp;lt;T&amp;gt; (T input);&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And let's say that we have some Handler&amp;lt;object&amp;gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: courier new;"&gt;Handler&amp;lt;object&amp;gt; myHandler = delegate (object o) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do something with the object&lt;br /&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now let's say that we have a method with takes a Handler&amp;lt;string&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: courier new;"&gt;void HandleStrings (Handler&amp;lt;string&amp;gt; handler, IEnumerable&amp;lt;string&amp;gt; strings)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach (string s in strings) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;handler (s);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;We want to pass myHandler to HandleStrings. A Handler&amp;lt;object&amp;gt; takes objects, and strings are objects, so anything which is a Handler&amp;lt;object&amp;gt; should also be a legal Handler&amp;lt;string&amp;gt;. This is an example of contravariance.&lt;br /&gt;&lt;br /&gt;It may surprise you to know, but the &lt;a href="http://en.wikipedia.org/wiki/Common_Language_Infrastructure"&gt;CLI&lt;/a&gt; has supported generic type variance since version 2. The rules are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Variant type parameters are only allowed in interfaces and delegate types.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Contravariant type parameters can only be used as by-value method parameter types.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Covariant type parameters can only be used as method return types and generic arguments to inherited interfaces.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Only reference types are variant (this isn't explicitly stated in the spec, but it is the case).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Languages may choose to ignore variance and treat all generic parameters as invariant.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;For whatever reason, the C# language team has so far chosen not to support generic type variance. Well, that will be changing in 2010. The preview given by Anders Hejlsberg at PDC '08 revealed that C# 4 will finally support variance. But who wants to wait? Especially considering that this has been a .NET VM feature since 2006. So you can now use this in gmcs if you pass -langversion:future.&lt;br /&gt;&lt;br /&gt;Covariance (which, as you will remember, can only be used as a method return type or as a generic argument to an inherited interface) is denoted with the "out" keyword before the type parameter identifier:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: courier new;"&gt;interface IFoo&amp;lt;out T&amp;gt; : IBar&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T Bat { get; }&lt;br /&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Contravariance (which is legal only as the type of a by-value method parameter) is denoted with the "in" keyword:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="font-family: courier new;"&gt;interface IFoo&amp;lt;in T&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void Bar (T bat);&lt;br /&gt;}&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So there you go! Now we just need to get Mono's VM variance support polished off. I'm sure I'll have good news for you about that shortly. Thanks goes to &lt;a href="http://mareksafar.blogspot.com/"&gt;Marek Safar&lt;/a&gt; for reviewing patches. If you have questions about how or why variance works (it's kind of tricky to get your head around), leave a comment. I might do a post delving into all of the little rules behind variance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-207754177809403426?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/207754177809403426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=207754177809403426' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/207754177809403426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/207754177809403426'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2009/02/c-4-is-now.html' title='C# 4 is NOW!'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-386809946646444840</id><published>2008-11-29T16:05:00.000-08:00</published><updated>2008-11-29T21:07:51.967-08:00</updated><title type='text'>Equality Now!</title><content type='html'>There are three primary ways to handle equality in .NET: overriding Object.Equals, overloading the == and != operators, and implementing IEquatable&amp;lt;T&amp;gt;. Framework Design Guidelines offers pretty good advice on when to use what. A quick summary:&lt;div&gt;&lt;ul&gt;&lt;li&gt;If you want custom equality logic, whatever else you might do, override Object.Equals. This method is used by the various data structures in System.Collections (and elsewhere in the BCL) to determine equality. It's the first best way to do equality.&lt;/li&gt;&lt;li&gt;IEquatable&amp;lt;T&amp;gt; should be implemented by structs with custom equality. Because calling Object.Equals on a struct involves boxing, &lt;span class="Apple-style-span" style="font-style: italic;"&gt;and&lt;/span&gt; the implementation for value types uses reflection (!!!!!), IEquatable&amp;lt;T&amp;gt; gets around both of those problems. When implementing IEquatable&amp;lt;T&amp;gt;, always override Object.Equals as well.&lt;/li&gt;&lt;li&gt;Operator overloading is a little bit tricky because it's really just a compiler feature. The compiler has a lookup rule for the operator implementation which takes the most derived types along the operands' type ancestry. Whereas Object.Equals is a virtual method whose overridden implementation will always be used, overloaded operators will only be used if both operands are of static (compile-time) types that are or derive from the types specified in the overload. Overloading operators is a matter of discretion. It's more commonly done with value than reference types. If you overload the equality operators, also override Equals (an implement IEquatable&amp;lt;T&amp;gt; if the type is a struct).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;When you are just overriding Equals, here is the pattern I find works the best:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public override bool Equals (object obj)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;MyRefType mine = obj as MyRefType;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return mine != null &amp;amp;&amp;amp; /* custom equality logic here */;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you want to overload operators and it's a reference type, here's the thing to do:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public override bool Equals (object obj)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;MyRefType mine = obj as MyRefType;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return mine == this;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public static bool operator == (MyRefType mine1, MyRefType mine2)&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;if (Object.ReferenceEquals (mine1, null)) {&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Object.ReferenceEquals (mine2, null);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return !Object.ReferenceEquals (mine2, null) &amp;amp;&amp;amp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;/* custom equality logic here /*;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public static bool operator != (MyRefType  mine1, MyRefType  mine2)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return !(mine1 == mine2);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you have a value type, here's the scenario without overriding the operators.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public override bool Equals (object obj)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return obj is MyValueType &amp;amp;&amp;amp; Equals ((MyValueType)obj);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public bool Equals (MyValueType mine)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return /* custom equality logic here */&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And here's the value type with operator overloads&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public override bool Equals (object obj)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return obj is MyValueType &amp;amp;&amp;amp; Equals ((MyValueType)obj);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public bool Equals (MyValueType mine)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return mine == this;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public static bool operator == (MyType mine1, MyType mine2)&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return /* custom equality logic here */&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;public static bool operator != (MyType  mine1, MyType  mine2)&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&amp;nbsp;&amp;nbsp;return !(mine1 == mine2);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;The purpose of the above patterns is to centralize the equality logic in one place. You'll notice in the example which uses all three approaches, the == operator is the only place with actual equality logic. I find this just makes thing easier. If you want, you can have custom logic in the != overload (the logical inverse of ==), but that means you have to make changes in two places if you alter the equality logic, and it's really easy to make a mistake with logic operators.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Want to share your tips for equality? Have a better pattern? Leave a comment!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-386809946646444840?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/386809946646444840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=386809946646444840' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/386809946646444840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/386809946646444840'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2008/11/equality-now.html' title='Equality Now!'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-4334280485804295486</id><published>2008-11-05T18:03:00.000-08:00</published><updated>2008-11-05T19:36:53.629-08:00</updated><title type='text'>Advanced Topics in Inefficiency: Anonymous Methods</title><content type='html'>This is the first in what may be a series of posts on various theoretical (and not so theoretical) corner cases in common code. Despite being obtuse, these issues are useful to explore both to avoid inefficiencies and to better understand what's happening behind the code. Today's topic: anonymous methods.&lt;br /&gt;&lt;blockquote style="font-family: courier;"&gt;class Foo()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void Bar()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var thing1 = new Thing();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var thing2 = new Thing();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoSomeStuff (() =&gt; thing1.Shimmy());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoOtherStuff(() =&gt; thing2.Shake());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/blockquote&gt;There is a potential memory problem with this method. It's not obvious from looking at the code, but both things must be garbage collected together. As long as there is an active reference to one, the other will live on as well. If 'Thing' is a heavy type, this could keep significant memory from being reclaimed on the heap. To better understand, let us look at how the C# compiler handles anonymous methods.&lt;br /&gt;&lt;br /&gt;The above example demonstrates "local variable capture." This means local variables from the enclosing method body can be used inside closures (such as the two lambdas above). To accomplish this, the C# compiler shunts the values of the local variables to an object. The type of the object is generated by the compiler. In essence, the compiler turns the above code into this:&lt;br /&gt;&lt;blockquote style="font-family: courier;"&gt;class Foo()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;class GeneratedTypeForMethodBar&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Thing thing1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Thing thing2;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void AnonymousMethod1()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;thing1.Shimmy();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void AnonymousMethod2()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;thing2.Shake();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void Bar()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var closure_object =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new GeneratedTypeForMethodBar();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;closure_object.thing1 = new Thing();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;closure_object.thing2 = new Thing();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoSomeStuff(closure_object.AnonymousMethod1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoOtherStuff(closure_object.AnonymousMethod2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/blockquote&gt;This is actually a very clever way of achieving local variable capture since it makes use of the CLI's pre-existing garbage collector to clean up the captured variables. The problem is, the compiler shunts all local variables to a single object. In our above example, the two anonymous methods do not reference any of the same local variables, but both local variables are stored in the same object. This can lead some captured variables to become prisoner variables: they are no longer needed, but they cannot be garbage collected. Suppose that our 'DoSomeStuff' method just invokes the delegate and returns. No problem. But now suppose that our 'DoOtherStuff' method holds on to the delegate, perhaps planing to invoke it later. Or suppose we were to return the second lambda, allowing the caller to hold the delegate as long as they please. That delegate holds a reference to the 'closure_object' which holds a reference to both Things, even though that delegate just needs 'thing2'. There is no way for any code to reach 'thing1' but it won't be garbage collected until we're done with 'thing2'.&lt;br /&gt;&lt;br /&gt;Solution?&lt;br /&gt;&lt;br /&gt;Well, we could modify the compiler to generate a type for each set of local variables that appear in only one anonymous method, like so:&lt;br /&gt;&lt;blockquote style="font-family: courier;"&gt;class Foo()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;class GeneratedTypeForMethodBar1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Thing thing1;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void AnonymousMethod()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;thing1.Shimmy();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;class GeneratedTypeForMethodBar2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Thing thing2;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void AnonymousMethod()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;thing2.Shake();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void Bar()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var closure_object1 =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new GeneratedTypeForMethodBar1();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;closure_object1.thing1 = new Thing();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var closure_object2 =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new GeneratedTypeForMethodBar2();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;closure_object2.thing2 = new Thing();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoSomeStuff(closure_object1.AnonymousMethod);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DoOtherStuff(closure_object2.AnonymousMethod);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/blockquote&gt;This poses problems as well. First of all, we are instantiating two (or more) generated-type objects rather than one. Object instantiation is not cheap and that could potentially slow down certain code. Also, this approach cannot be used to optimize more complex scenarios. Suppose we have five anonymous delegates, each referencing some of seven local variables like so: a {1 2} b {2 3} c {3 4 5} d {1 5 6} e {6 7}. In these situations we must default to the one-compiler-generated-type-for-everything approach.&lt;br /&gt;&lt;br /&gt;Ultimately, the lesson here is just to be aware of these potential issues. If you find via profiling that objects are not being garbage collected and you make heavy use of anonymous methods, you might want to examine your closures to make sure this isn't causing the problem.&lt;br /&gt;&lt;br /&gt;And what do people think about modifying the compiler as proposed above? Also, anyone who comes up with a better mechanism for local variable capture gets cool points. Double points if your solution doesn't require VM changes.&lt;br /&gt;&lt;br /&gt;P.S. Thanks to &lt;a href="http://mjhutchinson.com/"&gt;Michael&lt;/a&gt; for help with this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-4334280485804295486?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/4334280485804295486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=4334280485804295486' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/4334280485804295486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/4334280485804295486'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2008/11/advanced-topics-in-inefficiency.html' title='Advanced Topics in Inefficiency: Anonymous Methods'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-2782749769547151949</id><published>2008-10-10T02:13:00.000-07:00</published><updated>2008-10-10T03:13:06.218-07:00</updated><title type='text'>Mono.Upnp: A Bun In The Oven</title><content type='html'>&lt;a href="http://abock.org/2008/10/09/from-scott-the-new-new-zealander/"&gt;Aaron's post&lt;/a&gt; has piqued some interest, so I thought I'd give up the goods.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=" font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;WTF&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Mono.Upnp is a fully managed &lt;a href="http://en.wikipedia.org/wiki/UPnP"&gt;UPnP&lt;/a&gt; implementation. The client and server stacks are in separate libraries to give embedded devices a compact solution for either. The client library is a solid implementation of the UPnP standard designed to robustly cope with other, less compliant UPnP devices (seriously, no one actually implements the UPnP standard correctly. Especially not router manufacturers, may they die a thousand deaths). The client API is also highly extensible, allowing easy consumption of services which offer functionality not established in the spec. The server library offers developers an easy way to expose their services over UPnP: attributes indicate UPnP-visible members and the library handles all of the network plumbing. In addition, all of the official UPnP device and service APIs (the specs which sit on top of the UPnP architecture - for example, the MediaServer API) are wrapped both for client and server use.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Holy Shit!&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Indeed. Well, almost. All of the above sounds great, but it's not done yet. In fact, it's still quite experimental. While I've made great progress in &lt;a href="http://picasaweb.google.com/lunchtimemama/UPnP#5254382325622603826"&gt;impressive screenshots&lt;/a&gt;, actually &lt;span class="Apple-style-span" style="font-style: italic;"&gt;listening&lt;/span&gt; to your Banshee collection on a PS3 is still a few hack-o-thons off. But things are moving along nicely and I will certainly keep you up to date.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;OK&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;In the mean time, curious monkeys can find the source in the mono-upnp module of the Mono SVN. Like I said, you shouldn't be using this code, but you're welcome to check it out.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-2782749769547151949?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/2782749769547151949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=2782749769547151949' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/2782749769547151949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/2782749769547151949'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2008/10/monoupnp-bun-in-oven.html' title='Mono.Upnp: A Bun In The Oven'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-1076612218895194425</id><published>2007-11-01T13:10:00.000-07:00</published><updated>2007-11-01T13:23:12.682-07:00</updated><title type='text'>MemberExpression Question</title><content type='html'>Maybe someone can answer this for me. When C# is compiled into an Expression tree, the MemberInfo that is tied to a MemberExpression points to the most virtual/abstract definition of that member. For an example, take a look at &lt;a href="http://lunchtimemama.googlepages.com/Program.cs"&gt;this code&lt;/a&gt;. The Visitor class will print the declaring type of a member encountered in a MemberAccess Expression (ln 36). When ran in Orcas B2, it prints "BaseClass" rather than "ConcreteClass". Is this how it's supposed to behave? Does Mono behave this way? Is there a better way to get the MethodInfo of the concrete class than this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;// This goes in the Visitor.VisitMemberAccess method&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;MemberInfo mi = m.Expression.Type.GetMemeber(m.Member.Name)[0];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I ask because I'm looking for custom attributes which may only exist on the overridden members of the concrete classes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-1076612218895194425?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/1076612218895194425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=1076612218895194425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/1076612218895194425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/1076612218895194425'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/11/memberexpression-question.html' title='MemberExpression Question'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-3282954409205631223</id><published>2007-10-31T23:46:00.000-07:00</published><updated>2007-11-01T11:48:19.661-07:00</updated><title type='text'>Linq Me This Nut</title><content type='html'>The Banshee-to-Windows porting has been more or less done for a while and the code is about to be integrated into trunk. Since the end of the SoC, I've been occupying myself with a tangentially related project. Banshee talks to the &lt;a href="http://www.musicbrainz.org/"&gt;MusicBrainz&lt;/a&gt; database to get metadata on CDs. Currently it calls into the unmanaged libmusicbrainz library which is both old and no fun. Enter musicbrainz-sharp, my new project to implement a fully managed API for MusicBrainz. It's a very nice OO encapsulation of MusicBrainz's XMLWebService and it's really easy to use:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;Artist a = Artist.QuerySingle("The Magnetic Fields");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;foreach(Release r in a.Releases)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(r.Title);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Right now it lives in banshee's svn (thanks to &lt;a href="http://www.abock.org/"&gt;Aaron&lt;/a&gt; for setting me up with autotools et al). The API is 90% done, the documentation is 90% written, and the unit tests are at about 50% coverage. It's been my intension to create a Linq provider when 3.5 comes out, but for whatever reason the urge overcame me today. I did a quick job which only supports very specific cases, but the following code now works like a charm in Orcas:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;var query = from a in MB.Artists&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where a.Name == "Goodshirt"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select a;&lt;br /&gt;&lt;br /&gt;foreach(var artist in query) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;artist&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach(var release in artist.Releases) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine("\t{0}", release);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach(var track in release.Tracks)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine("\t\t{0}", track);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I was muy excited. There's some &lt;a href="http://blogs.msdn.com/mattwar/archive/2007/07/30/linq-building-an-iqueryable-provider-part-i.aspx"&gt;boilerplate code&lt;/a&gt; involved with writing a Linq provider. I hope Microsoft adds some base classes to the API. Linq is balls awesome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-3282954409205631223?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/3282954409205631223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=3282954409205631223' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/3282954409205631223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/3282954409205631223'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/10/linq-me-this-nut.html' title='Linq Me This Nut'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-1515003994872886582</id><published>2007-08-05T22:54:00.000-07:00</published><updated>2007-08-05T23:11:02.766-07:00</updated><title type='text'>Status Report Aug 5</title><content type='html'>This week:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;CD Burning is done&lt;br /&gt;&lt;/li&gt;&lt;li&gt;CD Playback is done&lt;br /&gt;&lt;/li&gt;&lt;li&gt;NotifyAreaPlugin works with the Windows system tray&lt;/li&gt;&lt;/ul&gt;Things are really coming together. I'll have new screenshots soon but I've got to go to bed now. We're out of the native code woods... for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-1515003994872886582?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/1515003994872886582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=1515003994872886582' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/1515003994872886582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/1515003994872886582'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/08/status-report-aug-5.html' title='Status Report Aug 5'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-727027303549170942</id><published>2007-07-31T19:54:00.001-07:00</published><updated>2007-07-31T20:44:08.885-07:00</updated><title type='text'>End of July Status</title><content type='html'>Here's the skinny on the Banshee port to Windows:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Major re-factoring of the audio CD code. I abstracted a bunch of Linux-specific code and implemented classes for Windows. Made some interfaces into abstract classes where helpful and re-jiggered some of the architecture.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The Cool Thing: It's all really pretty and audio CD detection works.&lt;/li&gt;&lt;li&gt;The Not Cool Thing: CD playback does not work. This is because Gstreamer on Windows doesn't handle cdda:/ URIs. This is because libcdio doesn't build on Windows. This is because, while it &lt;span style="font-style: italic;"&gt;used&lt;/span&gt; to build on Windows, the Visual Studio solution has terrible bitrot. Solutions:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Build with Cygwin and...&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Live with a dependency on cygwin0.dll, or&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Find some way of circumventing cygwin dependencies (ideal).&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Fix the Visual Studio solution. This consumed much of my time recently. I emailed the guy who previously maintained the VS solution, but he hasn't gotten back to me.&lt;/li&gt;&lt;li&gt;Write a new cdda handler for Gstreamer using the Win32 API. Ug.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Implementation of CD burning for Windows.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The Cool Thing: It's partially done (and was loads of fun), but I need to be able to test it to continue with the work.&lt;/li&gt;&lt;li&gt;The Not Cool Thing: I can't test it. This is because Banshee's Gstreamer transcoding code doesn't work. This is because it references libgnomevfs-2-0.dll and there is no libgnomevfs-2-0.lib against which to link and when I link against libgnomevfs-2-0.a, Visual Studio produces a malformed DLL which crashes upon loading. Solutions:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Build gnome-vfs with MSBuild. I gave that a try and it looks like a lot of work before it will work.&lt;/li&gt;&lt;li&gt;Contact whoever maintains Mono's Windows binaries and ask for their advice (ideal).&lt;/li&gt;&lt;li&gt;Remove the gnome-vfs code from libbanshee.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;Improvements to importing from iTunes.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The Cool Thing: Following Jonathan Pryor's &lt;a href="http://www.jprl.com/Blog/archive/development/mono/2007/Jul-15.html"&gt;post on monodocer performance&lt;/a&gt;, I switched from XmlDocument to XmlTextReader. Much memory savings. Not a lot of speed savings (XML handling isn't a bottleneck).&lt;/li&gt;&lt;li&gt;The Not Cool Thing: Nothing. The code is faster and prettier.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Misc. Other Things:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;I'm hoping the Gstreamer people will add a function export that I need: _gst_plugin_register_static. It's in the code  but it just isn't exported for Windows. Waiting to hear back.&lt;/li&gt;&lt;li&gt;The CD reading and burning code are from code example sites. Both are just encapsulation of COM interfaces. I'm 99% sure the CD reading code is license compatible (I'm still looking into it), but the CD burning stuff defiantly isn't. I've contacted both authors to see if they will release the code under MIT/X11. Waiting to hear back. If I can't get clearance, I'll have to do the COM wrappings myself. Ug.&lt;/li&gt;&lt;li&gt;Gtk is slow on Windows. Even when not debugging. Aaron's new view model should make things much better.&lt;/li&gt;&lt;li&gt;Gstreamer is slow on Windows. It's fine most of the time, but when the CPU gets hammered, the audio will become choppy. This doesn't happen when using DirectSound in similar situations. I don't know yet if it's a significant problem.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;I find I'm spending most of my time struggling with unmanaged code. When I tackle a new problem, like audio CDs, I hammer out the C# lickety split and have a great time. But then I hit a snag in native land (like the cdda/libcdio problem) and spend days trying to sort out the C libraries which is no fun. After a few days of wrestling with unmanaged code, I'll put it on the back burner and start on something else (CD burning or iTunes importing, for instance) but I really need to address these native issues. Tomorrow I'll start emailing around and see where I can get with cdda support in Gstreamer or gnomevfs linking on Windows. If you have info on this stuff, especially using Cygwin to build Windows stuff which is not Cygwin-dependent, please leave a comment.&lt;br /&gt;&lt;br /&gt;Peace,&lt;br /&gt;Scott.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-727027303549170942?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/727027303549170942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=727027303549170942' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/727027303549170942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/727027303549170942'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/07/end-of-july-status.html' title='End of July Status'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-3258533305162886970</id><published>2007-07-11T22:06:00.000-07:00</published><updated>2007-07-14T16:09:43.127-07:00</updated><title type='text'>Using Glib Callbacks with Managed Delegates on Windows</title><content type='html'>After wrestling with GStreamer for a week on Windows, I was delighted and disgusted to learn that the solution to my problem involved a simple string manipulation. My grin was mighty toothy. &lt;span style="font-style: italic;"&gt;Sharp&lt;/span&gt; teeth.&lt;br /&gt;&lt;br /&gt;I then had a new problem: Native Banshee code needs to call managed Banshee code every now and again (every 200 milliseconds) while Gstreamer is GStreaming. These callbacks are handled on the unmanaged side with glib mechanisms such as g_timeout_add. The problem is, glib uses the cdecl calling convention. If you try to set up a callback to managed delegates, which do not use the cdecl convention on Windows, you'll hit a nasty error when you call a delegate. Specifically, you'll  encounter my good friend, the every-cryptic,&lt;span class="fixed_width"  style="font-family:Courier,Monospaced;"&gt;&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;"An unhandled exception of type 'System.AccessViolationException' occurred in gtk-sharp.dll"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The solution (&lt;a href="http://groups.google.com/group/mono-soc-2007/msg/88652045494aebe3"&gt;thanks Miguel&lt;/a&gt;) is round-about, but with some jiggering in Visual Studio 2005 you can &lt;span style="font-style: italic;"&gt;Set it and Forget it©&lt;/span&gt;. Here's the step-by-step:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Download and install &lt;a href="http://www.activestate.com/Products/ActivePerl/"&gt;ActivePerl&lt;/a&gt; for Windows.&lt;/li&gt;&lt;li&gt;Grab &lt;a href="http://anonsvn.mono-project.com/viewcvs/trunk/gtk-sharp/gapi-cdecl-insert?rev=42168&amp;view=log"&gt;gtk-sharp/gapi-cdecl-insert&lt;/a&gt;. I just put it in C:\&lt;/li&gt;&lt;li&gt;You may need to edit gapi-cdecl-insert depending on whether or not I've committed these changes to SVN by the time you read this. Look at line 36. If it looks like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;`ildasm $assembly /out:$basename.raw`;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then you need to change it to this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;`ildasm "$assembly" /out:"$basename.raw"`;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Add quotes to &lt;span style="font-family:courier new;"&gt;$assembly and &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;$basename.raw&lt;/span&gt;). Do the same for line 49 by putting quotes around &lt;span style="font-family:courier new;"&gt;$basename.il&lt;/span&gt;, if they aren't already there.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Specify the Glib.CDeclCallback attribute for each delegate definition you will be calling with glib. For example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[GLib.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;&lt;span style="color: rgb(51, 153, 153);"&gt;CDeclCallback&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;internal delegate void&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 153, 153);font-family:courier new;" &gt;GstPlaybackEosCallback&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;(&lt;/span&gt;&lt;span style="color: rgb(51, 153, 153);font-family:courier new;" &gt;IntPtr &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;engine);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;Open the &lt;span style="font-weight: bold;"&gt;Properties&lt;/span&gt; for the C# library project with the delegates of interest.&lt;/li&gt;&lt;li&gt;Open the &lt;span style="font-weight: bold;"&gt;Build Events&lt;/span&gt; tab.&lt;/li&gt;&lt;li&gt;Click the &lt;span style="font-weight: bold;"&gt;Edit Post-build&lt;/span&gt; button.&lt;/li&gt;&lt;li&gt;First add the following:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;Call "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sdkvars.bat"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Obviously, adjust the install path for Visual Studio as necessary (there is no sufficient macro; grrr).&lt;/li&gt;&lt;li&gt;On the next line, add this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;Call C:\Perl\bin\perl.exe C:\gapi-cdecl-insert "$(TargetPath)"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Again, adjust your Perl and gapi-cdecl-insert paths as appropriate.&lt;/li&gt;&lt;li&gt;For whatever reason, VS fucks up the Perl script at the end, so you need to add one final line to the post-build events:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;Call ilasm /DLL /QUIET /DEBUG "$(TargetDir)\$(TargetName).il"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Remove the &lt;span style="font-family:courier new;"&gt;/DEBUG&lt;/span&gt; flag when you build for release.&lt;/li&gt;&lt;/ul&gt;Now try not to have too much fun fixing your glib-facilitated unmanaged-to-managed callback functions on Windows!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Update:&lt;/span&gt;&lt;br /&gt;Great and terrible news! None of the above craziness is necessary. Thanks to Jonathan Pryor who points out in the comments that all you need to do is specify the [UnmanagedFunctionPointer(CallingConvention.Cdecl)] attribute for the delegate definitions. No Perl necessary! This only works for the 2.0 framework.&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;span class="fixed_width"  style="font-family:Courier,Monospaced;"&gt;&lt;span style="font-family:times new roman;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-3258533305162886970?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/3258533305162886970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=3258533305162886970' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/3258533305162886970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/3258533305162886970'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/07/using-glib-callbacks-with-managed.html' title='Using Glib Callbacks with Managed Delegates on Windows'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-2192157309729189073</id><published>2007-06-25T10:39:00.001-07:00</published><updated>2007-06-25T10:53:56.629-07:00</updated><title type='text'>More News from the Front!</title><content type='html'>A quick update on two exciting developments:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Banshee now works on the .NET VM. Thanks to a tip from Javier of the &lt;a href="http://www.bibliateca.es/"&gt;Bibli@teca&lt;/a&gt; project who directed me toward a different set of GTK libraries.&lt;/li&gt;&lt;li&gt;Banshee now plays music. I've written a little DirectShow backend which provides all the niceties of playback: play/pause, seeking, volume control, &amp;amp;c. This is a temporary solution until I get GStreamer working, but it's nice to see this sucker actually do what it does.&lt;/li&gt;&lt;/ul&gt;That's all for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-2192157309729189073?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/2192157309729189073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=2192157309729189073' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/2192157309729189073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/2192157309729189073'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/06/more-news-from-front.html' title='More News from the Front!'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-4978087103061849927</id><published>2007-06-20T18:49:00.001-07:00</published><updated>2007-06-20T20:58:15.105-07:00</updated><title type='text'>Eets Alive!</title><content type='html'>After weeks of fiddling and false starts, this was the scene on my screen some 120 seconds ago:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_vUUhoww_aGI/RnnZTn6WDSI/AAAAAAAAAOc/G6lyyAmfS5Q/s1600-h/itsalive.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_vUUhoww_aGI/RnnZTn6WDSI/AAAAAAAAAOc/G6lyyAmfS5Q/s400/itsalive.jpg" alt="" id="BLOGGER_PHOTO_ID_5078328985991384354" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Banshee on Windows, baby!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-4978087103061849927?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/4978087103061849927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=4978087103061849927' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/4978087103061849927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/4978087103061849927'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/06/eets-alive.html' title='Eets Alive!'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_vUUhoww_aGI/RnnZTn6WDSI/AAAAAAAAAOc/G6lyyAmfS5Q/s72-c/itsalive.jpg' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-7524631039922686181</id><published>2007-06-02T14:46:00.000-07:00</published><updated>2007-06-02T14:54:00.179-07:00</updated><title type='text'>Status Report 1</title><content type='html'>Well, not much to report unfortunately. I've been desperately trying to get all of the build dependencies up and running on Cygwin. No easy task. For a detailed account of everything involved, and for a continued report of progress, see my &lt;a href="http://docs.google.com/Doc?id=ah4grsjk7k4c_68fpnbd7"&gt;project scratch pad&lt;/a&gt;. Aaron is moving right now so I'm one my own for the next week or so. I'm going to concurrently start work on the port while I try to get my Windows development environment up and running.&lt;br /&gt;&lt;br /&gt;As a post-script to my last post, I also added C# 3.0 Automatic Properties to gmcs. Look for that in SVN!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-7524631039922686181?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/7524631039922686181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=7524631039922686181' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/7524631039922686181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/7524631039922686181'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/06/status-report-1.html' title='Status Report 1'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-6420562262679014397</id><published>2007-05-07T10:33:00.000-07:00</published><updated>2007-05-07T23:43:53.427-07:00</updated><title type='text'>3rd is the one with the treasure chest</title><content type='html'>I seem to be on a compiler bent. I just committed the following C# 3.0 features to gmcs:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Variable type inference (the "var" keyword)&lt;/li&gt;&lt;li&gt;Anonymous types.&lt;/li&gt;&lt;li&gt;Implicitly typed arrays.&lt;/li&gt;&lt;li&gt;Object initialization.&lt;/li&gt;&lt;li&gt;Collection initialization.&lt;/li&gt;&lt;/ul&gt;They're in SVN right now, so go check 'em out! A word of warning: the new compiler errors associated with these features are not in place yet, so only write perfect code.&lt;br /&gt;&lt;br /&gt;This is my first time under the hood of a compiler (other than my &lt;a href="http://themonkeysgrinder.blogspot.com/2007/04/it-begins.html"&gt;brainfuck compiler&lt;/a&gt;). It took me a while to get my bearings but once I was acclimated, everything went smooth like bunnies. mcs is great to work on: it is very well designed. The foundation for all of these new features (particularly anonymous types) was already in place, I essentially just handled the new syntax. Thanks goes to Marek Safar for his help.&lt;br /&gt;&lt;br /&gt;Of course, all of these features are so much pretext for LINQ. Atsushi Eno &lt;a href="http://monkey.workarea.jp/lb/archive2007/5-06.html"&gt;is working&lt;/a&gt; on LINQ for XML and Antonello Provenzano has begun LINQ for SQL. Most of my hacking time this summer will go toward my Summer of Code project but if I have extra time I will defiantly look to the &lt;a href="http://www.mono-project.com/Olive"&gt;Olive project's&lt;/a&gt; LINQ implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-6420562262679014397?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/6420562262679014397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=6420562262679014397' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/6420562262679014397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/6420562262679014397'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/05/3rd-is-one-with-treasure-chest.html' title='3rd is the one with the treasure chest'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3573606178901893990.post-2610420954968990315</id><published>2007-04-12T12:40:00.000-07:00</published><updated>2007-04-11T21:46:11.223-07:00</updated><title type='text'>It Begins</title><content type='html'>First posts are hard to write so I'll do what I do best: talk about myself. I'm Scott Peterson. I attend New York University and my birthday is coming up soon (April 23rd). I enjoy whole milk and correcting people's grammar (but not their spelling).&lt;br /&gt;&lt;br /&gt;Here is a picture of me eating a taco:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_vUUhoww_aGI/RhQneueslwI/AAAAAAAAAJc/UyacZoh22Cw/s1600-h/taco.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 240px; height: 320px;" src="http://bp0.blogger.com/_vUUhoww_aGI/RhQneueslwI/AAAAAAAAAJc/UyacZoh22Cw/s320/taco.jpg" alt="" id="BLOGGER_PHOTO_ID_5049704491015509762" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Now that we're acquainted, let's to 't. This blog chronicles my Google Summer of Code project to port &lt;a href="http://en.wikipedia.org/wiki/Banshee_%28music_player%29"&gt;Banshee&lt;/a&gt; to &lt;a href="http://uncyclopedia.org/wiki/Windows"&gt;Windows&lt;/a&gt;. I may also occasionally post about my other OSS/Mono exploits. For example, I just finished a &lt;a href="http://en.wikipedia.org/wiki/Brainfuck"&gt;brainfuck&lt;/a&gt; compiler for the &lt;a href="http://en.wikipedia.org/wiki/Common_Language_Infrastructure"&gt;CLI&lt;/a&gt; (&lt;a href="http://en.wikipedia.org/wiki/.net_framework"&gt;.NET&lt;/a&gt; &amp;amp; &lt;a href="http://en.wikipedia.org/wiki/Mono_%28software%29"&gt;Mono&lt;/a&gt;). It is called &lt;a href="http://code.google.com/p/brainfucker/"&gt;brainfucker&lt;/a&gt;. It is written in C# and uses the fantastic &lt;a href="http://www.mono-project.com/Cecil"&gt;Mono.Cecil&lt;/a&gt; library (cred to &lt;a href="http://evain.net/blog/"&gt;JB Evain&lt;/a&gt;). It also has a &lt;a href="http://brainfucker.googlecode.com/files/brainfuckerGtk.exe.zip"&gt;Gtk interface&lt;/a&gt;, if that's your thing.&lt;br /&gt;&lt;br /&gt;Well, that's all for now. This is surely the beginning of something magnificent. I feel it in my bones!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3573606178901893990-2610420954968990315?l=themonkeysgrinder.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://themonkeysgrinder.blogspot.com/feeds/2610420954968990315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3573606178901893990&amp;postID=2610420954968990315' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/2610420954968990315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3573606178901893990/posts/default/2610420954968990315'/><link rel='alternate' type='text/html' href='http://themonkeysgrinder.blogspot.com/2007/04/it-begins.html' title='It Begins'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_vUUhoww_aGI/RhQneueslwI/AAAAAAAAAJc/UyacZoh22Cw/s72-c/taco.jpg' height='72' width='72'/><thr:total>9</thr:total></entry></feed>
