<?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-8858562858324946394</id><updated>2011-08-02T13:02:49.082-07:00</updated><category term='script'/><category term='C#'/><category term='garbage collector'/><category term='million rows'/><category term='IDisposable'/><category term='Microsoft'/><category term='T-SQL'/><category term='async'/><category term='.NET'/><category term='SQL Server'/><title type='text'>IDisposable</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bob</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>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8858562858324946394.post-7141564087991822377</id><published>2010-10-24T15:11:00.000-07:00</published><updated>2010-10-24T17:08:25.427-07:00</updated><title type='text'>MergeSort and LINQ</title><content type='html'>Here is an implementation of the merge sort algorithm, which operates on a sequence/list of items:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;using System.Linq;&lt;br /&gt;&lt;br /&gt;namespace MergeSort&lt;br /&gt;{&lt;br /&gt;    public static class MergeSort_Extensions&lt;br /&gt;    {&lt;br /&gt;        public static IEnumerable&amp;lt;T&amp;gt; MergeSort&amp;lt;T&amp;gt;(this IList&amp;lt;T&amp;gt; items, Comparison&amp;lt;T&amp;gt; comparison)&lt;br /&gt;        {&lt;br /&gt;            return MergeSortInternal&amp;lt;T&amp;gt;(items, items.Count, comparison);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static IEnumerable&amp;lt;T&amp;gt; MergeSort&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; items, Comparison&amp;lt;T&amp;gt; comparison)&lt;br /&gt;        {&lt;br /&gt;            return MergeSortInternal&amp;lt;T&amp;gt;(items, items.Count(), comparison);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static IEnumerable&amp;lt;T&amp;gt; MergeSortInternal&amp;lt;T&amp;gt;(IEnumerable&amp;lt;T&amp;gt; items, int count, Comparison&amp;lt;T&amp;gt; comparison)&lt;br /&gt;        {&lt;br /&gt;            Debug.Assert(items != null);&lt;br /&gt;            Debug.Assert(comparison != null);&lt;br /&gt;&lt;br /&gt;            if (count == 0)&lt;br /&gt;                yield break;&lt;br /&gt;&lt;br /&gt;            if (count == 1)&lt;br /&gt;            {&lt;br /&gt;                yield return items.First();&lt;br /&gt;                yield break;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // sort both halves recursively&lt;br /&gt;            IEnumerator&amp;lt;T&amp;gt; enumA = MergeSortInternal&amp;lt;T&amp;gt;(items.Take&amp;lt;T&amp;gt;(count / 2), count / 2, comparison).GetEnumerator();&lt;br /&gt;            IEnumerator&amp;lt;T&amp;gt; enumB = MergeSortInternal&amp;lt;T&amp;gt;(items.Skip&amp;lt;T&amp;gt;(count / 2), count - count / 2, comparison).GetEnumerator();&lt;br /&gt;&lt;br /&gt;            bool movedA = enumA.MoveNext();&lt;br /&gt;            bool movedB = enumB.MoveNext();&lt;br /&gt;            Debug.Assert(movedA &amp;amp;&amp;amp; movedB);&lt;br /&gt;&lt;br /&gt;            // merge&lt;br /&gt;            while (true)&lt;br /&gt;            {&lt;br /&gt;                if (comparison(enumA.Current, enumB.Current) &amp;gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    // swap enumerators&lt;br /&gt;                    IEnumerator&amp;lt;T&amp;gt; iterTemp = enumA;&lt;br /&gt;                    enumA = enumB;&lt;br /&gt;                    enumB = iterTemp;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                yield return enumA.Current;&lt;br /&gt;                if (enumA.MoveNext() == false)&lt;br /&gt;                {&lt;br /&gt;                    // return the remaining items&lt;br /&gt;                    do yield return enumB.Current;&lt;br /&gt;                    while (enumB.MoveNext());&lt;br /&gt;                    break;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;P.S. The code was formatted with http://formatmysourcecode.blogspot.com/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-7141564087991822377?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/7141564087991822377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=7141564087991822377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/7141564087991822377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/7141564087991822377'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2010/10/mergesort-and-linq.html' title='MergeSort and LINQ'/><author><name>Bob</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-8858562858324946394.post-3677487819913975524</id><published>2008-07-07T15:17:00.000-07:00</published><updated>2008-12-11T23:42:53.221-08:00</updated><title type='text'>Would you not? Yes or No?</title><content type='html'>Below is a screenshot of a website (odnoklassniki.ru), which demonstrates a wonderful UI principle of confusing the user. It translates: "Confirmation: Do you, really, not want to receive notifications of the changes in the group? [Yes] [No]"..&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-ib3qvHD7g/SHKW-pWILZI/AAAAAAAAA3w/Q5g-qySHf94/s1600-h/OdnoklassnikiPrompt.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_m-ib3qvHD7g/SHKW-pWILZI/AAAAAAAAA3w/Q5g-qySHf94/s400/OdnoklassnikiPrompt.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5220400921070546322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I remember, I knew exactly what I wanted before I was asked... Now I'm not so sure, really :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-3677487819913975524?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/3677487819913975524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=3677487819913975524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/3677487819913975524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/3677487819913975524'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2008/07/would-you-not-yes-or-no.html' title='Would you not? Yes or No?'/><author><name>Bob</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://3.bp.blogspot.com/_m-ib3qvHD7g/SHKW-pWILZI/AAAAAAAAA3w/Q5g-qySHf94/s72-c/OdnoklassnikiPrompt.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8858562858324946394.post-4835135518849581405</id><published>2008-07-07T15:13:00.000-07:00</published><updated>2008-12-11T23:42:53.537-08:00</updated><title type='text'>Virtual Machito</title><content type='html'>Vista can be puzzling at times.. For example, while I was copying files from "D:\Virtual Machines" directory, it caught my eye that the progress dialog was showing something else - "D:\Virtual Machito":&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m-ib3qvHD7g/SHKVo2uFSPI/AAAAAAAAA3o/DNLVCzCUnaU/s1600-h/VirtualMachito.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_m-ib3qvHD7g/SHKVo2uFSPI/AAAAAAAAA3o/DNLVCzCUnaU/s400/VirtualMachito.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5220399447191931122" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Very cute :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-4835135518849581405?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/4835135518849581405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=4835135518849581405' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/4835135518849581405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/4835135518849581405'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2008/07/virtual-machito.html' title='Virtual Machito'/><author><name>Bob</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://1.bp.blogspot.com/_m-ib3qvHD7g/SHKVo2uFSPI/AAAAAAAAA3o/DNLVCzCUnaU/s72-c/VirtualMachito.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8858562858324946394.post-2008464041156048153</id><published>2008-07-07T15:08:00.001-07:00</published><updated>2008-12-11T23:42:53.756-08:00</updated><title type='text'>Google "facker"</title><content type='html'>While signing up for a new Google account, I was asked, as a proof that I'm human, to enter a Captcha-word "facker":&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m-ib3qvHD7g/SHKUJqeuOSI/AAAAAAAAA3g/9lr-mRDJh8I/s1600-h/CaptchaFacker.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_m-ib3qvHD7g/SHKUJqeuOSI/AAAAAAAAA3g/9lr-mRDJh8I/s400/CaptchaFacker.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5220397811818707234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hilarious.. and just facking-awesome! :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-2008464041156048153?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/2008464041156048153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=2008464041156048153' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/2008464041156048153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/2008464041156048153'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2008/07/google-facker.html' title='Google &quot;facker&quot;'/><author><name>Bob</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://1.bp.blogspot.com/_m-ib3qvHD7g/SHKUJqeuOSI/AAAAAAAAA3g/9lr-mRDJh8I/s72-c/CaptchaFacker.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8858562858324946394.post-5252733843908769735</id><published>2008-07-07T14:28:00.000-07:00</published><updated>2008-12-11T23:42:53.913-08:00</updated><title type='text'>PicasaWeb sucks (life out of photographs)</title><content type='html'>I had a long-running suspicion that images uploaded to PicasaWeb don't look good in the browser when viewed at full zoom (via the tiny "zoom" button). Finally, I got some proof. Here is the small crop of a 2400x1600 photograph:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-ib3qvHD7g/SHKdMeZwaDI/AAAAAAAAA48/rd8spF_DFRg/s1600-h/PicasaWebBlur.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_m-ib3qvHD7g/SHKdMeZwaDI/AAAAAAAAA48/rd8spF_DFRg/s400/PicasaWebBlur.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5220407755720910898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the image presented by PicasaWeb in the browser lost its sharpness and detail. The results are quite disappointing... Could this be the right time to move to Flickr?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-5252733843908769735?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/5252733843908769735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=5252733843908769735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/5252733843908769735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/5252733843908769735'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2008/07/picasaweb-sucks-life-out-of-photos.html' title='PicasaWeb sucks (life out of photographs)'/><author><name>Bob</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://2.bp.blogspot.com/_m-ib3qvHD7g/SHKdMeZwaDI/AAAAAAAAA48/rd8spF_DFRg/s72-c/PicasaWebBlur.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8858562858324946394.post-7737819225035097719</id><published>2008-06-02T14:38:00.000-07:00</published><updated>2008-07-07T14:28:28.532-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='million rows'/><category scheme='http://www.blogger.com/atom/ns#' term='T-SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><category scheme='http://www.blogger.com/atom/ns#' term='script'/><title type='text'>A Million Little Rows</title><content type='html'>Some time ago, I found this handy T-SQL script on the Web, which creates a table with a million rows (1, 2, 3, ...  999999, 1000000):&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- Declare a variable to hold the&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- count of rows to be generated&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Declare&lt;/span&gt; @p_NumberOfRows Bigint&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- We need 1 million rows&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;Select&lt;/span&gt; @p_NumberOfRows=1000000;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;With&lt;/span&gt; Base &lt;span class="kwrd"&gt;As&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;    &lt;span class="kwrd"&gt;Select&lt;/span&gt; 1 &lt;span class="kwrd"&gt;as&lt;/span&gt; n&lt;br /&gt;    &lt;span class="kwrd"&gt;Union&lt;/span&gt; &lt;span class="kwrd"&gt;All&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;Select&lt;/span&gt; n+1 &lt;span class="kwrd"&gt;From&lt;/span&gt; Base &lt;span class="kwrd"&gt;Where&lt;/span&gt; n &amp;lt; Ceiling(SQRT(@p_NumberOfRows))&lt;br /&gt;),&lt;br /&gt;Expand &lt;span class="kwrd"&gt;As&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;    &lt;span class="kwrd"&gt;Select&lt;/span&gt; 1 &lt;span class="kwrd"&gt;as&lt;/span&gt; C&lt;br /&gt;    &lt;span class="kwrd"&gt;From&lt;/span&gt; Base &lt;span class="kwrd"&gt;as&lt;/span&gt; B1, Base &lt;span class="kwrd"&gt;as&lt;/span&gt; B2&lt;br /&gt;),&lt;br /&gt;Nums &lt;span class="kwrd"&gt;As&lt;/span&gt;&lt;br /&gt;(&lt;br /&gt;    &lt;span class="kwrd"&gt;Select&lt;/span&gt; Row_Number() &lt;span class="kwrd"&gt;OVER&lt;/span&gt;(&lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; C) &lt;span class="kwrd"&gt;As&lt;/span&gt; n&lt;br /&gt;    &lt;span class="kwrd"&gt;From&lt;/span&gt; Expand&lt;br /&gt;)&lt;br /&gt;&lt;span class="kwrd"&gt;Select&lt;/span&gt; n &lt;span class="kwrd"&gt;into&lt;/span&gt; BigTable &lt;span class="kwrd"&gt;from&lt;/span&gt; Nums &lt;span class="kwrd"&gt;Where&lt;/span&gt; n&amp;lt;=@p_NumberOfRows&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;-- Remove Maximum Recursion level constraint&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;OPTION&lt;/span&gt; (MaxRecursion 0);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It runs great with Microsoft SQL Server 2005.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-7737819225035097719?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/7737819225035097719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=7737819225035097719' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/7737819225035097719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/7737819225035097719'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2008/06/million-rows.html' title='A Million Little Rows'/><author><name>Bob</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-8858562858324946394.post-5291908741618260687</id><published>2008-06-01T11:14:00.000-07:00</published><updated>2008-11-12T15:21:46.090-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='async'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='garbage collector'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='IDisposable'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Dispose Design Pattern</title><content type='html'>Given all the benefits of the Garbage Collector (GC) in .NET, the IDisposable/Dispose pattern is a necessary evil. It does make the code more complicated, harder to manage, and more error-prone. However, if you want to rely solely on finalizers to release resources, your application isn't going to fly.&lt;br /&gt;&lt;br /&gt;Releasing resources (database connections, handles to open files, blocks of memory, etc.) as soon as they are no longer needed is prudent. Also, dropping the references to other objects is a great idea, because it helps the GC reclaim unused memory more efficiently. For the GC, the more null references, the better.&lt;br /&gt;&lt;br /&gt;To reiterate, the Dispose() method should be used to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Release managed resources (in the realm of CLR);&lt;/li&gt;&lt;li&gt;Release unmanaged resources (in the native realm);&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Drop references (set them to null).&lt;/li&gt;&lt;/ul&gt;There is one fortunate side-effect of the IDisposable pattern: it may be used for canceling pending asynchronous operations. Imagine a database query form, which can be closed by a user any moment. The best way to handle this situation is to implement the Dispose method on a class that performs the asynchronous query, which would close database connections, effectively, canceling the database request. One thing to note here is that in this scenario, concurrency comes into play, since Dispose may be invoked simultaneously with the async callbacks.&lt;br /&gt;&lt;br /&gt;Thus, Dispose() may also be used to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cancel any pending async operations.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;What are finalizers good for then? Since finalizers are not guaranteed to execute at all, and they impose a considerable overhead onto the GC - the answer is: pretty much nothing. According to MSDN, finalizers should be used to release unmanaged resources. There is another school of thought, which suggests to not use finalizers at all. In the context of our discussion, however, there is one beneficial use of finalizers:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;To warn if the Dispose() method hasn't been called (via asserting or logging).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;It should be self-evident from the failed assertion, who was responsible for disposing of the object properly. To make it even more apparent, one could capture the callstack in the constructor, which would identify the object's creator. The GC overhead can be avoided in the correct use-case by hinting the GC to skip the finalizer with the SuppressFinalize method.&lt;br /&gt;&lt;br /&gt;There is an IDisposable pattern (C# .NET) posted on &lt;a href="http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx"&gt;MSDN&lt;/a&gt;. I personally prefer the following variation:&lt;br /&gt;&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MyProject&lt;br /&gt;{&lt;br /&gt;  &lt;span class="kwrd"&gt;class&lt;/span&gt; MyClass:&lt;br /&gt;      IDisposable&lt;br /&gt;  {&lt;br /&gt;      ~MyClass()&lt;br /&gt;      {&lt;br /&gt;          DisposeOfUnmanagedResources();&lt;br /&gt;&lt;br /&gt;          &lt;span class="rem"&gt;// should have called Dispose!&lt;/span&gt;&lt;br /&gt;          Debug.Assert(&lt;span class="kwrd"&gt;false&lt;/span&gt;);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Dispose()&lt;br /&gt;      {&lt;br /&gt;          DisposeOfUnmanagedResources();&lt;br /&gt;          &lt;br /&gt;          &lt;span class="rem"&gt;// release managed resources&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;          GC.SuppressFinalize(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DisposeOfUnmanagedResources()&lt;br /&gt;      {&lt;br /&gt;          &lt;span class="rem"&gt;// release unmanaged resources&lt;/span&gt;&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(The sample above was formatted using &lt;a href="http://www.manoli.net/csharpformat/"&gt;http://www.manoli.net/csharpformat/&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Compared to the original pattern on MSDN, here:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;DisposeOfManagedResources()/DisposeOfUnmanagedResources() replace the ambiguous Dispose(bool) method;&lt;/li&gt;&lt;li&gt;The finalizer ~MyClass() would raise an assertion (in Debug builds) if the user of MyClass hasn't called Dispose().&lt;/li&gt;&lt;/ul&gt;That's it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8858562858324946394-5291908741618260687?l=idisposable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://idisposable.blogspot.com/feeds/5291908741618260687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8858562858324946394&amp;postID=5291908741618260687' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/5291908741618260687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8858562858324946394/posts/default/5291908741618260687'/><link rel='alternate' type='text/html' href='http://idisposable.blogspot.com/2008/06/idisposable.html' title='Dispose Design Pattern'/><author><name>Bob</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></feed>
