<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Doron&amp;#39;s .NET Space</title><link>http://blogs.microsoft.co.il/blogs/dorony/</link><description>A .NET Blog by Doron Yaacoby</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/DoronSpace" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Visual Studio 2010 Beta 2: My 5 Minutes Impressions</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/iFFDIBTVT8I/visual-studio-2010-beta-2-my-5-minutes-impressions.aspx</link><pubDate>Sun, 25 Oct 2009 21:26:18 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:430343</guid><dc:creator>dorony</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=430343</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/10/25/visual-studio-2010-beta-2-my-5-minutes-impressions.aspx#comments</comments><description>&lt;p&gt;So I just installed VS 2010 beta 2, played with it for 5 whole minutes, and I have to say it looks pretty damn good.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Performance was horrid on Beta 1, but now it seems to be much improved.&lt;/li&gt;    &lt;li&gt;Startup time is still too long if you ask me.&lt;/li&gt;    &lt;li&gt;Opening the Fonts and Colors dialog is still the slowest thing in the world.&lt;/li&gt;    &lt;li&gt;But the Add Reference dialog opens really fast! Finally they realized it is better to default on the project reference tab there.&lt;/li&gt;    &lt;li&gt;The new WPF UI is beautiful. I like the “Code Optimized” web settings that remove all the non-critical toolbars and panels and leave lots of room for the code.&lt;/li&gt;    &lt;li&gt;The new IntelliTrace (or historical debugging) feature &lt;a href="http://blogs.msdn.com/ianhu/archive/2009/05/13/historical-debugging-in-visual-studio-team-system-2010.aspx"&gt;looks very interesting&lt;/a&gt;.&lt;/li&gt;    &lt;li&gt;F# Interactive seems to always be open, even on a C# project. Could be a useful tool, so I should probably get serious about learning F#.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I would also like to point out &lt;a href="http://blogs.msdn.com/ricom/archive/2009/10/19/my-history-of-visual-studio-part-10-final.aspx"&gt;this excellent article&lt;/a&gt;, which talks about the VS2010 architecture. It’s great to see how Microsoft “dogfoods” its own products and in the process makes them better for the rest of us. It stands to reason that if WPF can work for a project like Visual Studio, and TFS can handle the entire Microsoft organization, these could be good choices for us simpletons. &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=430343" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/10/25/visual-studio-2010-beta-2-my-5-minutes-impressions.aspx</feedburner:origLink></item><item><title>Running VSTS tests without mstest.exe</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/JR9imtHOvaA/running-vsts-tests-without-mstest-exe.aspx</link><pubDate>Wed, 21 Oct 2009 17:41:22 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:429007</guid><dc:creator>dorony</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=429007</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/10/21/running-vsts-tests-without-mstest-exe.aspx#comments</comments><description>&lt;p&gt;I’ve been looking at ways to run VSTS tests without using the actual Visual Studio testing framework. It all started when I wanted to integrate code-coverage in our TeamCity daily build. All the &lt;a href="http://weblogs.asp.net/lkempe/archive/2008/03/30/integration-of-ncover-into-team-city-for-tech-head-brothers.aspx"&gt;solutions I found&lt;/a&gt; were using the NUnit runner for this, and while I could have used mstest.exe to run the tests when I’m gathering code-coverage, I didn’t want to. Why? Well, because:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;TeamCity doesn’t use it to run the tests, so I might get different result from the regular test-run and the code-coverage test-run.&lt;/li&gt;    &lt;li&gt;It requires me to install Visual Studio on the server.&lt;/li&gt;    &lt;li&gt;It creates annoying TestResult folders.&lt;/li&gt;    &lt;li&gt;It requires maintaining a testrun.config file.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;In essence, using mstest.exe just seems a lot more cumbersome. Still, all our tests are indeed using the VSTS attributes, so I need a way to run them “NUnit-style”, i.e. without mstest.exe. TestDriven.Net and TeamCity already seem to be doing this, but without exposing anything that I could use. Google did not help, neither. So, I turned to &lt;a href="http://stackoverflow.com/questions/1564681/running-vsts-tests-without-mstest-exe"&gt;ask at Stackoverflow.com&lt;/a&gt;. After a while, an answer was received by a fellow named Bryan Cook: an addin to NUnit exist, but alas, it turns out it doesn’t support the latest NUnit version. Kindly enough, Bryan just &lt;a href="http://www.bryancook.net/2009/10/mstest-nunit-adapter.html"&gt;went and fixed it&lt;/a&gt;. Not a trivial task, mind you, as I had a look at the code, and it seems that the NUnit API went through quite a lot of changes going into version 2.5.&lt;/p&gt;  &lt;p&gt;Anyway, you can go over and download the addin &lt;a href="http://snippetware.googlecode.com/files/ExactMagic.MstsAdapter.zip"&gt;from right here&lt;/a&gt;. Thanks Bryan!&lt;/p&gt;  &lt;p&gt;On a different note, we ended up deciding to switch all our tests to NUnit at the end, but I’m sure this could come handy in the future :)&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=429007" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/TDD/default.aspx">TDD</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/10/21/running-vsts-tests-without-mstest-exe.aspx</feedburner:origLink></item><item><title>Improving Upon LINQ’s Distinct</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/LrfgmE6dsMc/improving-upon-linq-s-distinct.aspx</link><pubDate>Sat, 01 Aug 2009 09:15:51 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:373080</guid><dc:creator>dorony</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=373080</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/08/01/improving-upon-linq-s-distinct.aspx#comments</comments><description>&lt;p&gt;Suppose you have a collection of objects, and you want only the distinct values. You could easily use Linq for this, like that:&lt;/p&gt;  &lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var items = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;[] {&lt;span style="color:#006080;"&gt;&amp;quot;BMW&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;Fiat&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;Ferrari&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;Fiat&amp;quot;&lt;/span&gt;};&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var distinctItems = items.Distinct();&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This uses the default comparer for the objects in order to see if they’re equal. There’s also another overload, which lets you specify your own comparer. This is its signature:&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;TSource&amp;gt; Distinct&amp;lt;TSource&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt; IEnumerable&amp;lt;TSource&amp;gt; source, IEqualityComparer&amp;lt;TSource&amp;gt; comparer);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;It accepts an IEqualityComparer to compare between items. But the usage of IEqualityComparer is a bit annoying, as you have to create you own class that implements that interface. It would be nice if I could just do this:&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var items = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;[] {&lt;span style="color:#006080;"&gt;&amp;quot;HI&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;HELLO&amp;quot;&lt;/span&gt;};&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var distinctItems = items.Distinct((str1, str2) =&amp;gt; str1.ToLower().Equals(str2.ToLower()));&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;So in this example we would expect the result array to contain two items and not four.&lt;/p&gt;

&lt;p&gt;Let’s see if we can make this happen. We’ll create our own IEqualityComparer which accepts a lambda.&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; LambdaEqualityComparer&amp;lt;T&amp;gt; : IEqualityComparer&amp;lt;T&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Func&amp;lt;T,T,&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&amp;gt; _comparison;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; LambdaEqualityComparer(Func&amp;lt;T,T,&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&amp;gt; comparison)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;         _comparison = comparison;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; Equals(T x, T y)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _comparison(x, y);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; GetHashCode(T obj)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum16"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum17"&gt;  17:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; obj.GetHashCode();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum18"&gt;  18:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum19"&gt;  19:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Here we have a class that accepts the comparison lambda as a parameter. Now we can add our own Distinct extension method:&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; EnumerableExtensions&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;{&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;TSource&amp;gt; Distinct&amp;lt;TSource&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt; IEnumerable&amp;lt;TSource&amp;gt; source, Func&amp;lt;TSource,TSource,&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&amp;gt; comparison)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; source.Distinct(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; LambdaEqualityComparer&amp;lt;TSource&amp;gt;(comparison));&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Once again, let’s try to run this:&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var items = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;[] {&lt;span style="color:#006080;"&gt;&amp;quot;HI&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;HELLO&amp;quot;&lt;/span&gt;};&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var distinctItems = items.Distinct((str1, str2) =&amp;gt; str1.ToLower().Equals(str2.ToLower()));&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Well, that didn’t work out well at all&lt;/strong&gt;&lt;/em&gt;. It returns a &lt;strong&gt;four&lt;/strong&gt; items array. Digging into it a bit, we can see that the problem is in our LambdaEqualityComparer class, specifically with our naive GetHashCode implementation (lines 15-17 above):&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; GetHashCode(T obj)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;{&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; obj.GetHashCode();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;As you can see our comparison doesn’t come into play at all for GetHashCode. It also appears that the original Distinct uses (at least in some cases) GetHashCode and not Equals to determine if two objects are equal, and so our lambda comparison doesn’t even run. &lt;/p&gt;

&lt;p&gt;We need to attack this differently, then. Let’s try to make this code work:&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var items = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;[] {&lt;span style="color:#006080;"&gt;&amp;quot;HI&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;hi&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;,&lt;span style="color:#006080;"&gt;&amp;quot;HELLO&amp;quot;&lt;/span&gt;};&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;var distinctItems2 = items.DistinctBy(str1 =&amp;gt; str1.ToLower());&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;So in this new DistinctBy method, we’re not comparing two items, but selecting something to compare by for every item. The implementation is similar to before, and here is the entire thing:&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; EnumerableExtensions&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;TSource&amp;gt; DistinctBy&amp;lt;TSource, TSelection&amp;gt;(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt; IEnumerable&amp;lt;TSource&amp;gt; source, Func&amp;lt;TSource, TSelection&amp;gt; selector)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; source.Distinct(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SelectorEqualityComparer&amp;lt;TSource, TSelection&amp;gt;(selector));&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; SelectorEqualityComparer&amp;lt;TSource, TSelection&amp;gt; : IEqualityComparer&amp;lt;TSource&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Func&amp;lt;TSource, TSelection&amp;gt; _selector;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; SelectorEqualityComparer(Func&amp;lt;TSource, TSelection&amp;gt; selector)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt;         {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt;             _selector = selector;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum15"&gt;  15:&lt;/span&gt;         }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum16"&gt;  16:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum17"&gt;  17:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; Equals(TSource x, TSource y)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum18"&gt;  18:&lt;/span&gt;         {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum19"&gt;  19:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; Object.Equals(_selector(x), _selector(y));&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum20"&gt;  20:&lt;/span&gt;         }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum21"&gt;  21:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum22"&gt;  22:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; GetHashCode(TSource obj)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum23"&gt;  23:&lt;/span&gt;         {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum24"&gt;  24:&lt;/span&gt;             &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; _selector(obj).GetHashCode();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum25"&gt;  25:&lt;/span&gt;         }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum26"&gt;  26:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum27"&gt;  27:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;As you can see, both the implementation of GetHashCode and Equals now use our selector lamda, and so the code works, and all is well with the world.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=373080" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Linq/default.aspx">Linq</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/08/01/improving-upon-linq-s-distinct.aspx</feedburner:origLink></item><item><title>ArcGIS Web ADF 9.3 – Is it Any Better?</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/1aQBTYCVYfI/arcgis-web-adf-9-3-is-it-any-better.aspx</link><pubDate>Sat, 13 Jun 2009 20:53:36 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:337709</guid><dc:creator>dorony</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=337709</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/06/13/arcgis-web-adf-9-3-is-it-any-better.aspx#comments</comments><description>&lt;p&gt;A while back I’ve posted &lt;a href="http://blogs.microsoft.co.il/blogs/dorony/archive/2007/11/21/a-geographic-nightmare.aspx"&gt;my opinion&lt;/a&gt; about the ArcGIS Web ADF 9.2. It wasn’t a positive one. Since then, I’ve had a chance to work a little with the new version – the ADF 9.3, and even attended a seminar held by Rex Hansen, which – as I understood - is one of the main contributors to the design of the Web ADF.&lt;/p&gt;  &lt;p&gt;On the surface it seems that the Web ADF took a leap forward at 9.3. It is now built upon the Microsoft Ajax library, instead of ESRI’s own callback-based solution (you know, the whole ICallbackEventHandler headache). Performance should be better, as the map now uses a custom .ashx handler to serve the images, instead of doing a bunch of full postbacks. But the question that remains is – Is the API any better? Are simple stuff simple? Is customization any easier?&lt;/p&gt;  &lt;p&gt;Sadly, the answer to that seems to be a big NO. Almost none of the issues I addressed in my original post were fixed. The API is still overly complex. Resources, functionalities and all these so-called abstractions remain in place, emphasizing the strength of the JavaScript API’s simplicity. And yes, there are still about a billion classes that are named “Converter” in the API. It seems like ESRI insists that you write the entire namespace before every class you use.&lt;/p&gt;  &lt;p&gt;Ajax is a bit easier this time around, since we can use ScriptManager to register client scripts, but it still took us a while to figure out how to make it all play nicely together (&lt;a href="http://resources.esri.com/help/9.3/arcgisserver/adf/dotnet/developer/ADF/ajax_postbackmodel.htm"&gt;this article&lt;/a&gt; provides some solutions, by the way). I hate having to read mountains of documentation before I can get anything done (on the bright side – at least there &lt;em&gt;is&lt;/em&gt; documentation), and trying to explain a newbie programmer about the difference between a “partial postback” and a callback is &lt;em&gt;hard. &lt;/em&gt; &lt;/p&gt;  &lt;p&gt;There are some more unpleasant surprises for you here. &lt;a href="http://blogs.microsoft.co.il/blogs/noams/"&gt;Noam Sheffer&lt;/a&gt; (hebrew link) mailed me about a problem he had. It seems that the map control still initiates a full postback to the page with every zoom operation.&amp;#160; This is of course bad for performance, and also caused him issues with maintaining the state of some of his controls. Checking out &lt;a href="http://demos.eaglegis.co.nz/general-newzealandcached/default.aspx"&gt;an example site&lt;/a&gt; with Fiddler or Firebug, can show you that this is indeed the case. &lt;/p&gt;  &lt;p&gt;And a word about the seminar by Rex Hansen. He showed some of the product’s new features, performance tips, and solutions to common problems. Thing is, I don’t care about being able to customize the MapTips template. It shows that ESRI focus is on the wrong thing – instead of simplifying the API, they’re adding more features so that it is even more complex. &lt;/p&gt;  &lt;p&gt;Therefore, I still recommend anyone with a choice to go for one of the REST APIs. I’ve only worked with the JavaScript APIs, but I hear that Silverlight and Flex are similar and are equally simple. For now, I’m keeping my strong belief that doing anything complex with the Web ADF is putting yourself in a world of hurt.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=337709" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/GIS/default.aspx">GIS</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/06/13/arcgis-web-adf-9-3-is-it-any-better.aspx</feedburner:origLink></item><item><title>ArcGIS JavaScript API: IE Memory Leak Fix</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/PFAQZSKO0To/arcgis-javascript-api-ie-memory-leak-fix.aspx</link><pubDate>Sat, 09 May 2009 09:30:53 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:284666</guid><dc:creator>dorony</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=284666</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/05/09/arcgis-javascript-api-ie-memory-leak-fix.aspx#comments</comments><description>&lt;p&gt;Since version 1.2 of the ArcGIS Javascript API, we&amp;#39;ve noticed a strange issue in both IE6 and IE7. When zooming in, memory consumption of the iexplore.exe process takes a huge jump and reaches up to 800-900 megabytes. When the operation ends, it goes back down to 50-60 megabytes. This has caused us a great deal of sorrow, as it sometimes caused our users&amp;#39; systems to hang. &lt;/p&gt; &lt;p&gt;&lt;a href="http://forums.esri.com/Thread.asp?c=158&amp;amp;f=2396&amp;amp;t=276110&amp;amp;mc=5#msgid855271"&gt;This post&lt;/a&gt; in the ESRI forums explains, and also provides a fix. Apparently, the upgrade to dojo 1.2 has caused this zoom-animation related issue. To fix it, you should create a javascript file with this text:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e1c393d2-bd08-4ea0-8b68-8a8a68949bea" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Arial;font-size:12;"&gt;&lt;div&gt;&lt;span style="color:#008000;"&gt;/*&lt;/span&gt;&lt;span style="color:#008000;"&gt;
 * override the dojo 1.2, 1.3 version of dojo._setOpacity to revert back to the dojo 1.1 implementation
 * this version doesnt allow multiple filters on an element, but it is free from the memory spike issue &lt;/span&gt;&lt;span style="color:#008000;"&gt;*/&lt;/span&gt;&lt;span style="color:#000000;"&gt;
(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;() {
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;var&lt;/span&gt;&lt;span style="color:#000000;"&gt; d &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; dojo;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt;(dojo.isIE) {
    dojo._setOpacity &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#008000;"&gt;/*&lt;/span&gt;&lt;span style="color:#008000;"&gt;DomNode&lt;/span&gt;&lt;span style="color:#008000;"&gt;*/&lt;/span&gt;&lt;span style="color:#000000;"&gt;node, &lt;/span&gt;&lt;span style="color:#008000;"&gt;/*&lt;/span&gt;&lt;span style="color:#008000;"&gt;Number&lt;/span&gt;&lt;span style="color:#008000;"&gt;*/&lt;/span&gt;&lt;span style="color:#000000;"&gt;opacity){
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt;(opacity &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;var&lt;/span&gt;&lt;span style="color:#000000;"&gt; filterRE &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;/&lt;/span&gt;&lt;span style="color:#000000;"&gt;FILTER:[^;]*;?&lt;/span&gt;&lt;span style="color:#000000;"&gt;/&lt;/span&gt;&lt;span style="color:#000000;"&gt;i;
        node.style.cssText &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; node.style.cssText.replace(filterRE, &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt;(node.nodeName.toLowerCase() &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;tr&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
          d.query(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt; td&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, node).forEach(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(i){
            i.style.cssText &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; i.style.cssText.replace(filterRE, &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
          });
        }
      }&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;{
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;var&lt;/span&gt;&lt;span style="color:#000000;"&gt; o &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Alpha(Opacity=&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; opacity &lt;/span&gt;&lt;span style="color:#000000;"&gt;*&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;100&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;)&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        node.style.filter &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; o;
      }
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt;(node.nodeName.toLowerCase() &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;tr&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;){
        d.query(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt; td&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, node).forEach(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(i){
          i.style.filter &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; o;
        });
      }
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; opacity;
    };
  }
})();&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Reference this javascript file from every page that has a reference to the Javascript API, and you&amp;#39;re good to go. &lt;/p&gt;
&lt;p&gt;Still, one can&amp;#39;t help but wonder how the ESRI QA guys didn&amp;#39;t notice this obvious shortcoming (which will be fixed at 1.4, they claim). Maybe they only used machines with lots of RAM. That&amp;#39;s how we missed this at first... :)&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=284666" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/GIS/default.aspx">GIS</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/TECH/default.aspx">TECH</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/ArcGIS+Javascript+API/default.aspx">ArcGIS Javascript API</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/05/09/arcgis-javascript-api-ie-memory-leak-fix.aspx</feedburner:origLink></item><item><title>Writing Maintainable Javascript Guidelines</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/S5iXb-NXK5g/writing-maintainable-javascript-guidelines.aspx</link><pubDate>Fri, 03 Apr 2009 18:08:49 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:264397</guid><dc:creator>dorony</dc:creator><slash:comments>3</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=264397</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/04/03/writing-maintainable-javascript-guidelines.aspx#comments</comments><description>&lt;p&gt;We&amp;#39;ve been doing a lot of Javascript development lately, while writing an Ajax-based web application. Up until recently, my team&amp;#39;s Javascript experience consisted mainly of the occasional disable-that-checkbox function inside an .aspx web-form. Nothing wrong with that, I guess, but it doesn&amp;#39;t really count. If you&amp;#39;re going to write a lot of Javascript, you &lt;em&gt;have &lt;/em&gt;to do so in an organized and clean way, or you&amp;#39;ll have a maintenance nightmare on your hands. &lt;/p&gt; &lt;p&gt;This is not because Javascript is a bad language. It can be quite beautiful actually. But it does allow to work in ways that are not elegant, so I would like to show you some tips on what you should do, and what you should avoid - &lt;a href="http://msdn.microsoft.com/en-us/library/ms229042.aspx"&gt;Framework Design Guidelines&lt;/a&gt; style.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;DO &lt;/strong&gt;use separate .js files to store your Javascript code.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AVOID &lt;/strong&gt;writing a lot of Javascript inside an .aspx form.&lt;/p&gt; &lt;p&gt;When you do the shift to a heavily scripted client, and you begin writing loads of Javascript, this approach fails miserably, for several reasons:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Performance - .js files are usually cached on the client side, and .aspx are not, as they usually contain dynamic data. Also, .js files can usually be compressed, so they get even lighter to download. &lt;/li&gt; &lt;li&gt;Maintenance - It is just easier to maintain the script code when it is in a separate file.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;DO &lt;/strong&gt;use different .js files for different modules.&lt;/p&gt; &lt;p&gt;It might seem obvious, but I&amp;#39;ve seen .js files that contain thousands of lines of un-related code. Again, this is hard to maintain. In C# we like having a separate file for each class, don&amp;#39;t we? Well, Javascript shouldn&amp;#39;t be a lot different. If you&amp;#39;re worried about the performance penalty of having many files, there are tools you can use to combine your scripts to a single file on deployment. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;DO&lt;/strong&gt; use a Javascript library instead of rolling your own infrastructure. &lt;/p&gt; &lt;p&gt;Really, these days it is just silly to write your own Ajax implementation, or your own collection types. Libraries like &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;, &lt;a href="http://www.asp.net/ajax/"&gt;ASP.NET Ajax&lt;/a&gt; and &lt;a href="http://www.dojotoolkit.org/"&gt;Dojo&lt;/a&gt;, already do so much for you. This will save you a lot of time and effort, and will also allow you to create cross-browser Javascript that works even on crappy-old browsers such as IE6.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;CONSIDER &lt;/strong&gt;writing only object-oriented Javascript.&lt;/p&gt; &lt;p&gt;Most Javascript libraries will allow you to write your code in an object-oriented manner, based on the prototype model available in the language. Object oriented code is easier to follow and understand. And yes, you even get the benefits of inheritance, design-patterns and all that good OO stuff you know from C#. Here&amp;#39;s how a class in the Dojo library is declared:&lt;/p&gt; &lt;p&gt; &lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:93a10f67-d1c9-4e7d-83d5-5065d9051f67" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Arial;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;dojo.declare(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Person&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;, {         
   constructor: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(name, age, currentResidence){
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.name&lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt;name;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.age&lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt;age;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.currentResidence&lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt;currentResidence;
    },
    moveToNewCity: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(newState) 
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.currentResidence&lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt;newState;
    } 

});&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;As you can see, we have a constructor, fields, methods and all. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AVOID &lt;/strong&gt;using a lot of global variables and functions.&lt;/p&gt;
&lt;p&gt;This is really just good programming behavior. Globals are bad! That&amp;#39;s what they always used to tell you, and this is still correct. Unlike C# or Java, Javascript allows you to define global variables and global functions. In fact, for many this is the standard way of scripting. I know it was for me. But when you start having hundreds and thousands lines of code, which access some variable that was defined in god-only-knows-where, you&amp;#39;ll see that it&amp;#39;s a bad idea. When you have 5, 10 or 20 .js files, you just don&amp;#39;t want to take the chance that two of them define the same function or variable, do you?&lt;/p&gt;
&lt;p&gt;Granted, you can&amp;#39;t avoid using &lt;em&gt;some &lt;/em&gt;globals, but you should keep this to a bare minimum. Our pattern for global functions is to use them as gateway-only to some class. Usually they will be event-handlers which just create a class and call one of its methods. We pass data around from constructor to constructor instead of defining it globally. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AVOID &lt;/strong&gt;specifing an Html element ID in a class declaration. &lt;/p&gt;
&lt;p&gt;This is bad:&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:f189d4a8-210e-4b31-9241-688cb9657436" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Arial;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;dojo.declare(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;ButtonHider&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;, {         
   hide: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;() 
    {
         $get(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;MyButton&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;).style.display &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;none&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
    } 
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;This is good:&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:9e9f11bd-51f9-4e38-8337-3835c7721432" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Arial;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;dojo.declare(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;ButtonHider&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;, {         
   hide: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(buttonId) 
    {
         $get(buttonId).style.display &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;none&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
    } &lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Also good:&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:8a6adc59-fe3d-489e-98b2-a098ab70bc11" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Arial;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;dojo.declare(&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ButtonHider&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;, {         
    constructor: function(buttonId) {    
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.buttonId &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; buttonId;
    }
       hide: function() {
         $&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.buttonId).style.display &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#800000;"&gt;none&lt;/span&gt;&lt;span style="color:#800000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
    } &lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Not only this makes your code more generic, but in ASP.NET is essential. ID&amp;#39;s for server controls can easily be changed if they&amp;#39;re dropped inside some container. You&amp;#39;ll want to pass the ClientID property of the button you want to hide to the class above, and not the actual ID.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DO &lt;/strong&gt;remember that Javascript is a functional and dynamic language, and use that to make your code more readable.&lt;/p&gt;
&lt;p&gt;Functions can be passed around as data in Javascript. Properties and methods can be added to any object. You can misuse these features, of course, but when used correctly they make Javascript a very powerful language. Having classes doesn&amp;#39;t make it C# code! Here&amp;#39;s a &lt;a href="http://stackoverflow.com/questions/61088/hidden-features-of-javascript"&gt;StackOverflow thread&lt;/a&gt; to get you started on some of Javascript&amp;#39;s less known features.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DO &lt;/strong&gt;maintain coding standards to your Javascript.&lt;/p&gt;
&lt;p&gt;If you want your code to be readable, you need to have standards. Among other things, we use camelCase naming for functions, use underscore prefix to signal &amp;quot;private&amp;quot; members (even if the language does allow them to be accessed outside, the underscore suggest the user of your code to not do so), and use the syntax &amp;#39;var arr = [];&amp;#39; to define an Array (and never &amp;#39;new Array()&amp;#39;). What are your standards? Define them, and have everyone follow them. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CONSIDER &lt;/strong&gt;writing unit-tests for your Javascript.&lt;/p&gt;
&lt;p&gt;I admit we&amp;#39;re still taking baby-steps in that direction, but as our code-base gets more and more complex, we&amp;#39;ll have to cover it with unit-tests for it not to break on us. Here are &lt;a href="http://stackoverflow.com/questions/209418/what-are-some-javascript-unit-testing-and-mocking-frameworks-you-have-used"&gt;some frameworks&lt;/a&gt; recommendations we&amp;#39;re considering to aid us in that.&lt;/p&gt;
&lt;p&gt;To conclude, I would like to say that crappy code can be written in any language. If your application is Javascript oriented, it is no excuse to write bad code. The guidelines I have put are nothing new. Mainly, they only remind you to also use them when writing Javascript, and not only in your favorite compiled language. &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=264397" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Javascript/default.aspx">Javascript</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/04/03/writing-maintainable-javascript-guidelines.aspx</feedburner:origLink></item><item><title>ESRI JavaScript API: Now with Error Handling</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/ZoWIt59ILPs/esri-javascript-api-now-with-error-handling.aspx</link><pubDate>Tue, 03 Mar 2009 17:58:18 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:240333</guid><dc:creator>dorony</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=240333</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/03/03/esri-javascript-api-now-with-error-handling.aspx#comments</comments><description>&lt;p&gt;The JavaScript API v1.3 &lt;a href="http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/help/jshelp_start.htm#jshelp/new_v13.htm"&gt;has been released&lt;/a&gt;, and it now supports error and timeout handling. Finally! We actually had gone and implemented this feature ourselves by overriding the esri.request function, but it was a hack that we&amp;#39;ll be glad to be rid off. I can&amp;#39;t really understand why this wasn&amp;#39;t there to begin with, but still - happyness. &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=240333" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/ArcGIS+Javascript+API/default.aspx">ArcGIS Javascript API</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/03/03/esri-javascript-api-now-with-error-handling.aspx</feedburner:origLink></item><item><title>Pretty Quick Sort With C# 3.0</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/1E_gOZT3jgY/pretty-quick-sort-with-c-3-0.aspx</link><pubDate>Thu, 29 Jan 2009 19:28:41 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:218886</guid><dc:creator>dorony</dc:creator><slash:comments>5</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=218886</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/01/29/pretty-quick-sort-with-c-3-0.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://themechanicalbride.blogspot.com/2009/01/f-sharpest-of-sharps.html"&gt;Jafar Husain writes&lt;/a&gt; about the prettiness of F#&amp;#39;s type inference, but what I really liked in his post was his C# 3.0 implementation for Quick Sort:&lt;/p&gt; &lt;p&gt; &lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:988911cb-e363-4cc2-941b-9bfbb7f7c748" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Arial;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#008080;"&gt; 1&lt;/span&gt; &lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;static&lt;/span&gt;&lt;span style="color:#000000;"&gt; IEnumerable&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; QuickSort&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt; IEnumerable&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; list)
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 2&lt;/span&gt; &lt;span style="color:#000000;"&gt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;where&lt;/span&gt;&lt;span style="color:#000000;"&gt; T : IComparable
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 3&lt;/span&gt; &lt;span style="color:#000000;"&gt;{
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 4&lt;/span&gt; &lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#000000;"&gt;!&lt;/span&gt;&lt;span style="color:#000000;"&gt;list.Any())
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 5&lt;/span&gt; &lt;span style="color:#000000;"&gt;    {
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 6&lt;/span&gt; &lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Enumerable.Empty&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;();
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 7&lt;/span&gt; &lt;span style="color:#000000;"&gt;    }
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 8&lt;/span&gt; &lt;span style="color:#000000;"&gt;    var pivot &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; list.First();
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 9&lt;/span&gt; &lt;span style="color:#000000;"&gt;    var smaller &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; list.Where(item &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; item.CompareTo(pivot) &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;).QuickSort();
&lt;/span&gt;&lt;span style="color:#008080;"&gt;10&lt;/span&gt; &lt;span style="color:#000000;"&gt;    var larger &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; list.Where(item &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; item.CompareTo(pivot) &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#800080;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;).QuickSort();
&lt;/span&gt;&lt;span style="color:#008080;"&gt;11&lt;/span&gt; &lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#008080;"&gt;12&lt;/span&gt; &lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; smaller.Concat(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt;[]{pivot}).Concat(larger);
&lt;/span&gt;&lt;span style="color:#008080;"&gt;13&lt;/span&gt; &lt;span style="color:#000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Yes, the F# implementation is more concise, but Jafar really reminded how concise can C# be as well. When I first heard about C# 3.0&amp;#39;s var keyword, I belonged to the group that worried about code getting unreadable. Now I&amp;#39;ve grown to realize that type information can be over-rated. Sometimes it is just irrelevant noise.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=218886" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/C_2300_/default.aspx">C#</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2009/01/29/pretty-quick-sort-with-c-3-0.aspx</feedburner:origLink></item><item><title>Extending the ArcGIS Javascript API</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/2GJzV10z7Pc/extending-the-arcgis-javascript-api.aspx</link><pubDate>Sat, 08 Nov 2008 17:58:18 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:163031</guid><dc:creator>dorony</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=163031</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/11/08/extending-the-arcgis-javascript-api.aspx#comments</comments><description>&lt;p&gt;Working with &lt;a href="http://blogs.microsoft.co.il/blogs/dorony/archive/2008/09/30/arcgis-server-9-3-javascript-api-impressions.aspx"&gt;the new Javascript API&lt;/a&gt; for ArcGIS Server 9.3, I am now writing quite a bit of javascript. If you try and write large amounts of javascript code (I would consider &amp;gt;200 lines as large enough) without using objects, soon enough you&amp;#39;re going to have an unreadable nightmare in your hands.&lt;/p&gt; &lt;p&gt;In order for the code to be maintainable, I&amp;#39;ve realized I have to take advantage of &lt;a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/object-orientation"&gt;dojo&amp;#39;s object-orientation&lt;/a&gt; capabilities, and especially &lt;a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/object-orientation/inheritance"&gt;inheritance&lt;/a&gt;. This allows me to extend ESRI&amp;#39;s default objects, compensate for missing behaviors, and add logic of my own. Luckily, in javascript the can&amp;#39;t mark their objects sealed, or need to remember to mark methods as &amp;quot;virtual&amp;quot;, so extending this API&amp;#39;s objects is easier than doing so in the ADF. &lt;/p&gt; &lt;p&gt;For instance, suppose you want an ArcGISDynamicMapServiceLayer to tell you which layers are currently visible for it. Thing is, the API only exposes a &lt;a href="http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/help/jsapi/arcgisdynamicmapservicelayer.htm#setVisibleLayers"&gt;setVisibleLayers&lt;/a&gt; method, but not a getVisibleLayers(). So let&amp;#39;s try and add this, shall we?&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:94079669-545e-48e8-bec0-791253b9cfae" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Microsoft Sans Serif;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#008080;"&gt; 1&lt;/span&gt; &lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;doron.common.js&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 2&lt;/span&gt; &lt;span style="color:#008000;"&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;dojo.require(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;esri.map&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 3&lt;/span&gt; &lt;span style="color:#000000;"&gt;      
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 4&lt;/span&gt; &lt;span style="color:#000000;"&gt;      dojo.declare(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Doron.ExtendedDynamicMapServiceLayer&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, esri.layers.ArcGISDynamicMapServiceLayer, {
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 5&lt;/span&gt; &lt;span style="color:#000000;"&gt;        constructor: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt; () {
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 6&lt;/span&gt; &lt;span style="color:#000000;"&gt;            dojo.connect(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;onLoad&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt; () {
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 7&lt;/span&gt; &lt;span style="color:#000000;"&gt;                &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;._currentVisibleLayers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;._getDefaultVisibleLayers();          
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 8&lt;/span&gt; &lt;span style="color:#000000;"&gt;            });
&lt;/span&gt;&lt;span style="color:#008080;"&gt; 9&lt;/span&gt; &lt;span style="color:#000000;"&gt;        },
&lt;/span&gt;&lt;span style="color:#008080;"&gt;10&lt;/span&gt; &lt;span style="color:#000000;"&gt;        setVisibleLayers: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;(layers) {
&lt;/span&gt;&lt;span style="color:#008080;"&gt;11&lt;/span&gt; &lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;._currentVisibleLayers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; layers;
&lt;/span&gt;&lt;span style="color:#008080;"&gt;12&lt;/span&gt; &lt;span style="color:#000000;"&gt;           &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt;dojo&amp;#39;s way of calling base method - so that default behavior is preserved&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#008080;"&gt;13&lt;/span&gt; &lt;span style="color:#008000;"&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.inherited(arguments);
&lt;/span&gt;&lt;span style="color:#008080;"&gt;14&lt;/span&gt; &lt;span style="color:#000000;"&gt;             
&lt;/span&gt;&lt;span style="color:#008080;"&gt;15&lt;/span&gt; &lt;span style="color:#000000;"&gt;        },
&lt;/span&gt;&lt;span style="color:#008080;"&gt;16&lt;/span&gt; &lt;span style="color:#000000;"&gt;        getCurrentVisibleLayers: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt;() {
&lt;/span&gt;&lt;span style="color:#008080;"&gt;17&lt;/span&gt; &lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;._currentVisibleLayers;
&lt;/span&gt;&lt;span style="color:#008080;"&gt;18&lt;/span&gt; &lt;span style="color:#000000;"&gt;        },
&lt;/span&gt;&lt;span style="color:#008080;"&gt;19&lt;/span&gt; &lt;span style="color:#000000;"&gt;        _getDefaultVisibleLayers: &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="color:#000000;"&gt; () {
&lt;/span&gt;&lt;span style="color:#008080;"&gt;20&lt;/span&gt; &lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;var&lt;/span&gt;&lt;span style="color:#000000;"&gt; defaultVisibleLayers &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; [];
&lt;/span&gt;&lt;span style="color:#008080;"&gt;21&lt;/span&gt; &lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;var&lt;/span&gt;&lt;span style="color:#000000;"&gt; i&lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; i &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.layerInfos.length; i&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;) {
&lt;/span&gt;&lt;span style="color:#008080;"&gt;22&lt;/span&gt; &lt;span style="color:#000000;"&gt;                &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.layerInfos[i].defaultVisibility)
&lt;/span&gt;&lt;span style="color:#008080;"&gt;23&lt;/span&gt; &lt;span style="color:#000000;"&gt;                    defaultVisibleLayers.push(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.layerInfos[i].id);
&lt;/span&gt;&lt;span style="color:#008080;"&gt;24&lt;/span&gt; &lt;span style="color:#000000;"&gt;            }
&lt;/span&gt;&lt;span style="color:#008080;"&gt;25&lt;/span&gt; &lt;span style="color:#000000;"&gt;            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; defaultVisibleLayers;
&lt;/span&gt;&lt;span style="color:#008080;"&gt;26&lt;/span&gt; &lt;span style="color:#000000;"&gt;        }
&lt;/span&gt;&lt;span style="color:#008080;"&gt;27&lt;/span&gt; &lt;span style="color:#000000;"&gt;      });&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I am using dojo.declare to declare my new class, which inherits from esri.layers.ArcGISDynamicMapServiceLayer. My constructor first saves the layers that are visible by default in a field (this can only be done once the layer is loaded, so I&amp;#39;m registering myself to that event). I also override setVisibleLayers(), so that when it is called, I remember to update that field as well.&amp;nbsp; Now I can easily expose the getCurrentVisbleLayers() method.&lt;/p&gt;
&lt;p&gt;This class is something you can put in a .js file and reference everywhere you want - it is a much better approach than putting all your scripts inside the .html/.aspx/.whatever file.&lt;/p&gt;
&lt;p&gt;A page that would use it, might look like this:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:517dbcb5-21db-463a-864a-3e5fe3e88440" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;overflow:auto;font-family:Microsoft Sans Serif;font-size:14.25;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD HTML 4.01//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/strict.dtd&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;html &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;lang&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;head&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;meta &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;http-equiv&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; content&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;text/html; charset=utf-8&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;title&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Dynamically Create Map Service Layer List&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;title&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;link &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;rel&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;stylesheet&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; href&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;http://serverapi.arcgisonline.com/jsapi/arcgis/1.1/js/dojo/dijit/themes/tundra/tundra.css&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;script &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; src&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;script&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
     &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;script &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; src&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;doron.common.js&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;script&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;script &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;
      dojo.require(&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;esri.map&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;);
   &lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt; init() {
        map &lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;=&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt; esri.Map(&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;map&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;);

        layer &lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;=&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt; Doron.ExtendedDynamicMapServiceLayer(&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;);
        
        map.addLayer(layer);
      }
      
      &lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#0000FF;"&gt;function&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt; showVisibleLayers() {
        alert( layer.getCurrentVisibleLayers().join(&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;,&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="background-color:#F5F5F5;color:#000000;"&gt;));
      }
      dojo.addOnLoad(init);
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;script&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;head&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;body&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; 
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;div &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;map&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; class&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;tundra&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; style&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;width:600px; height:400px; border:1px solid #000;&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;div&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;input &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;button&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; onclick&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;showVisibleLayers()&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; value&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Show Visible Layers&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;body&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;html&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here I just took one of ESRI&amp;#39;s samples, and replaced their class with mine. I also added a button that shows the layers that are currently visible. The reference to &amp;quot;doron.common.js&amp;quot; allows me to use my own class that overrides the ESRI one.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Hope this was helpful. If you know of any more ways to make life with the Javascript API more comfortable, feel free to share.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=163031" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/GIS/default.aspx">GIS</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/TECH/default.aspx">TECH</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/ArcGIS+Javascript+API/default.aspx">ArcGIS Javascript API</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/11/08/extending-the-arcgis-javascript-api.aspx</feedburner:origLink></item><item><title>ArcGIS Server 9.3 Javascript API Impressions</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/RUM9VuK3D44/arcgis-server-9-3-javascript-api-impressions.aspx</link><pubDate>Tue, 30 Sep 2008 08:50:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:148110</guid><dc:creator>dorony</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=148110</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/09/30/arcgis-server-9-3-javascript-api-impressions.aspx#comments</comments><description>&lt;p&gt;After a long wait, I&amp;#39;ve finally been able to start using the &lt;a href="http://resources.esri.com/arcgisserver/apis/javascript/arcgis/"&gt;new Javascript API&lt;/a&gt; that comes with ArcGIS Server 9.3. And the truth? It&amp;#39;s pretty great.&lt;/p&gt; &lt;p&gt;It was difficult to start with, though. I didn&amp;#39;t realize that the actual API (.js files and images mostly) doesn&amp;#39;t come with the AGS installation discs - you have to request that separately. I have no idea why they won&amp;#39;t just let you download an installation zip, as anyone is free to use the API &lt;a href="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1"&gt;via this link here&lt;/a&gt;. Our internal network doesn&amp;#39;t have an Internet connection, and even if it did, I wouldn&amp;#39;t want to rely on unneeded external resources in my application.&lt;/p&gt; &lt;p&gt;Well, I finally got the bits and &amp;quot;installed&amp;quot; them - and by that I mean followed the readme.html file that comes with the disc and tells you to copy this directory over there, and edit that .js file and that .CSS file. An installation script would have been in order, and now I have to create one myself, which I am too lazy to do, but I will. I promise.&lt;/p&gt; &lt;p&gt;Also, the installation doesn&amp;#39;t come with an esri.debug.js file as is costumed with Javascript API&amp;#39;s. The .js file is a &amp;quot;compiled&amp;quot; one, and is completely obfuscated and unreadable. Gosh, I can&amp;#39;t understand ESRI&amp;#39;s constant need to obfuscate everything they make. The Web ADF DLLs are also obfuscated, and the only ones they&amp;#39;re hurting are the developers who use their product. If you still wish to be able to &amp;quot;step into&amp;quot; the ESRI scripts, I recommend that you use &lt;a href="http://javascript.about.com/library/blformat.htm"&gt;this website here&lt;/a&gt; to create your own esri.debug.js. It still won&amp;#39;t be the clearest thing, as all the variables will still be &amp;#39;meaningfully&amp;#39; named, but it is better than nothing.&lt;/p&gt; &lt;p&gt;Well, anyway, enough ranting, eh? Finally there&amp;#39;s an API from ESRI that I rather like! You can produce with this mapping applications with code that is actually readable. Look at &lt;a href="http://resources.esri.com/help/9.3/arcgisserver/apis/javascript/arcgis/demos/toolbars/toolbar_navigation.html"&gt;this sample&lt;/a&gt; (and view source) to see how easy it is to create a map with a toolbar. And the beauty is that it is easy even without a designer. I guess that since they couldn&amp;#39;t rely on anyone using Javascript to use a designer, they had to make the code usable, and they got it right. &lt;/p&gt; &lt;p&gt;The outcome is that the code is a lot more extensible. It took me a few minutes to change this code to use the &lt;a href="http://www.telerik.com/products/aspnet-ajax/controls/toolbar/overview.aspx"&gt;RadToolbar&lt;/a&gt; control. In the Web ADF, on the other hand, the controls are meant to use as-is (preferably with the cool-yet-kinda-silly &amp;quot;application builder&amp;quot; they have inside the manager application. Or at least the VS2005 designer). Therefore they are &lt;a href="http://blogs.microsoft.co.il/blogs/dorony/archive/2007/11/21/a-geographic-nightmare.aspx"&gt;a lot less&lt;/a&gt; extensible. Yes, they give you more out of the box, like a TOC control. But it will cost you dearly to try to do something &lt;i&gt;different. &lt;/i&gt;For this current application I have to build a dynamic TOC which can hold up to 200 layers, coming from different map objects, depending on the user. The prospect of making that work with the Web ADF is a bit daunting, but combining the js API and the REST services of ArcGIS 9.3 should make this a lot simpler.&lt;/p&gt; &lt;p&gt;So for now I am rather pleased. Things behave as they should - there aren&amp;#39;t many surprises and heads banging on desks. I am a bit concerned about writing more Javascript - we are still at VS 2005, so no intellisense for us, and a heavy reliance on the documentation (which is pretty good, by the way). Another concern is the usage of another Javascript library - &lt;a href="http://dojotoolkit.org/"&gt;Dojo&lt;/a&gt;. We are already using ASP.NET Ajax (the RAD controls use this as well), and now adding Dojo and ESRI&amp;#39;s own .js files, and maybe even &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt; I&amp;#39;ve been hearing a lot about - this is going to make for a big download to our clients. It does seem pretty weird that ESRI is using ASP.NET Ajax for the new .NET ADF controls, and Dojo for the Javascript API. Oh well.&lt;/p&gt; &lt;p&gt;To summarize, I would say ESRI has a winner with the new REST + Javascript combination. I doubt that I would now bother with anything that has ADF in its namespace - I&amp;#39;m guessing I would use the Javascript API for the client side, and open a direct ServerContext if I need to do something on the server. I&amp;#39;ll keep you posted on how this worked for me. &lt;/p&gt; &lt;p&gt;Shana Tova!&lt;/p&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=148110" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/GIS/default.aspx">GIS</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/TECH/default.aspx">TECH</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/ArcGIS+Javascript+API/default.aspx">ArcGIS Javascript API</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/09/30/arcgis-server-9-3-javascript-api-impressions.aspx</feedburner:origLink></item><item><title>StackOverFlow.com is Open, and it's Great</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/zTwXlASuU58/stackoverflow-com-is-open-and-it-s-great.aspx</link><pubDate>Mon, 15 Sep 2008 19:09:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:140013</guid><dc:creator>dorony</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=140013</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/09/15/stackoverflow-com-is-open-and-it-s-great.aspx#comments</comments><description>&lt;p&gt;If you haven&amp;#39;t heard about it, &lt;a href="http://stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt; is the new baby of &lt;a href="http://www.codinghorror.com"&gt;Jeff Atwood&lt;/a&gt; and &lt;a href="http://www.joelonsoftware.com/"&gt;Joel Spolsky&lt;/a&gt;. The concept is as simple as it can be: creating the most massive programming FAQ in the world. Questions are asked, answers are given, and the best answers appear on top.&lt;/p&gt; &lt;p&gt;I was in the private beta of this site, and I can be a witness that this works really well. Never was there a forum or a newsgroup in which I asked a question about programming and received &lt;i&gt;good&lt;/i&gt; answers so quickly. Also: the simple-yet-clever UI of Stack Overflow can teach all a meaningful lesson. This is how web-sites should be built.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.joelonsoftware.com/items/2008/09/15.html"&gt;The public beta has launched&lt;/a&gt; today, so go ahead and give it a try. &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=140013" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/09/15/stackoverflow-com-is-open-and-it-s-great.aspx</feedburner:origLink></item><item><title>Wanted: A Usable Installer Technology</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/MTW4h43jbIQ/wanted-a-usable-installer-technology.aspx</link><pubDate>Sun, 10 Aug 2008 19:28:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:129602</guid><dc:creator>dorony</dc:creator><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=129602</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/08/10/wanted-a-usable-installer-technology.aspx#comments</comments><description>&lt;p&gt;On Friday I was at the Israeli Alt.NET conference, &lt;a href="http://blogs.microsoft.co.il/blogs/urig/archive/2008/08/09/why-you-want-to-be-a-part-of-alt-net-israel.aspx"&gt;which was great&lt;/a&gt;. One thing that kept coming up was the frustration of everyone with current Installers technologies. I am using Visual Studio Setup Project, which is rather usable, but &lt;a href="http://blogs.microsoft.co.il/blogs/dorony/archive/2008/06/04/visual-studio-setup-project-annoyance.aspx"&gt;has many disadvantages&lt;/a&gt;, with the main one being the lack of ability to build it outside of Visual Studio. &lt;/p&gt; &lt;p&gt;I&amp;#39;ve also tried using &lt;a href="http://wix.sourceforge.net/"&gt;WiX&lt;/a&gt;, but its XML &amp;quot;UI&amp;quot; and incredible learning curve left me a bit puzzled. The Alt.NET guys assured me that I wasn&amp;#39;t the only one. They also bitched about Installshield and other technologies. &lt;/p&gt; &lt;p&gt;At the conference I also heard about &lt;a href="http://www.finalbuilder.com/"&gt;FinalBuilder&lt;/a&gt; for the first time. This is a popular software that allows you to create a powerful build script using a very simple GUI. You can choose from all manner of tasks, such as creating a web-site in IIS, or setting up a virtual PC. &lt;/p&gt; &lt;p&gt;And my point is this: Using FinalBuilder&amp;#39;s trial for the first time made me think - this is exactly what I would look for in a software that let me create installation scripts. Picking tasks such as &amp;quot;Update web site authentication in IIS&amp;quot; or &amp;quot;register to GAC&amp;quot; and putting them in a nice list. From that I could get a working MSI. &lt;/p&gt; &lt;p&gt;If someone went ahead and made this &amp;quot;FinalInstaller&amp;quot;, I&amp;#39;m sure he would enjoy a nice income. Go for it, startup guys.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=129602" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Deployment/default.aspx">Deployment</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/alt-net-israel/default.aspx">alt-net-israel</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/08/10/wanted-a-usable-installer-technology.aspx</feedburner:origLink></item><item><title>WPF Designer/Developer Paradigm - Does It Really Work?</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/t18h0jI5JIE/wpf-designer-developer-paradigm-does-it-really-work.aspx</link><pubDate>Tue, 05 Aug 2008 11:54:57 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:128637</guid><dc:creator>dorony</dc:creator><slash:comments>4</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=128637</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/08/05/wpf-designer-developer-paradigm-does-it-really-work.aspx#comments</comments><description>&lt;p&gt;All the WPF presentations I&amp;#39;ve seen made a big deal about how this technology allows you to separate the work of the designer and the developer. The designer can go about, designing away with the Expression tools, crafting a XAML file. Then the developer can add C# logic to the relevant CS file. &lt;/p&gt; &lt;p&gt;When I actually tried to do something with WPF, it immediately seemed suspicious to me. XAML, apparently, is also code. Not only that, it is also tightly coupled to the accompanying &amp;quot;code-behind&amp;quot;. There seem to be some things that you just can&amp;#39;t do with XAML - and I&amp;#39;m talking about visuals - like &lt;a href="http://blogs.microsoft.co.il/blogs/dorony/archive/2008/03/10/wpf-video-flipping-utility.aspx"&gt;making a video resize correctly&lt;/a&gt;. Anyway, while coding I kept going back and forth between the XAML and the code until I got the result I wished for.&lt;/p&gt; &lt;p&gt;Now, I&amp;#39;d be the first to admit that I&amp;#39;m not WPF pro, but I do have experience with ASP.NET, and it is the same way there - It is good to have a separation between display code and behavioral code, but I just don&amp;#39;t think that it would ever work if someone handed me an &amp;quot;.aspx&amp;quot; file and told me to &amp;quot;just add my code to that&amp;quot;.&lt;/p&gt; &lt;p&gt;I think that it might work if the developer and the designer worked together (i.e. same desktop) on creating a window. Or if the designer works only on very limited things, such as control templates and styles. But coding a complete XAML for a window with Expression and passing it on to the developer? I doubt that the latter will be able to read the damn thing, let alone work with it. &lt;/p&gt; &lt;p&gt;Then again, I might be wrong. I really have no idea, as I don&amp;#39;t know anyone who works with WPF on a daily basis and has a designer in his team. Just had an itch to talk about this.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=128637" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/WPF/default.aspx">WPF</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/08/05/wpf-designer-developer-paradigm-does-it-really-work.aspx</feedburner:origLink></item><item><title>Design Patterns - The Fun Way</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/QtZC5V3XbR4/design-patterns-the-fun-way.aspx</link><pubDate>Sat, 19 Jul 2008 19:17:15 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:122893</guid><dc:creator>dorony</dc:creator><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=122893</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/07/19/design-patterns-the-fun-way.aspx#comments</comments><description>&lt;p&gt;Anyone who&amp;#39;s ever tried to read the traditional &lt;a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=pd_bbs_sr_3?ie=UTF8&amp;amp;s=books&amp;amp;qid=1216494163&amp;amp;sr=8-3"&gt;GoF design patterns book&lt;/a&gt;, or any other book on the subject for that matter, has probably been bored to death. This is sad, since there is a lot of smarts in these patterns that people have already thought of for us, and using them - when appropriate - should really become a second nature to every programmer. &lt;/p&gt; &lt;p&gt;No worry, though, since I will now tell you the best possible way to learn about the classic design patterns, and that is to read &lt;a href="http://www.amazon.com/Head-First-Design-Patterns/dp/0596007124"&gt;Head First Design Patterns&lt;/a&gt;. I am now reading this book, which I borrowed from a friend, and it is really a joy to go through. With clear examples, lots of humor and a whole bunch of drawings and pictures - the &amp;quot;head first&amp;quot; way of teaching really seem to work. &lt;/p&gt; &lt;p&gt;You really have to read this to understand, but when a book contains, for example, sessions of two patterns that are being interviewed by a talk-show host, you can see that something special is going on. The authors have gone out of their way to find the best way to get each piece of knowledge into your head and make you remember it.&lt;/p&gt; &lt;p&gt;The only disadvantage of this book that I could find is that all the examples are in Java. It&amp;#39;s not much of an issue, except in chapters such as the one about the Observer pattern, where mentioning the way C#&amp;#39;s events implement this seems mandatory to me. &lt;/p&gt; &lt;p&gt;Nevertheless, if you&amp;#39;re going to buy a single design patterns book - this should be it. I&amp;#39;m definitely going to have all the programmers in my team read it.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=122893" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Books/default.aspx">Books</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/07/19/design-patterns-the-fun-way.aspx</feedburner:origLink></item><item><title>Why I Like My Job</title><link>http://feedproxy.google.com/~r/DoronSpace/~3/ooDxcbYHqX8/why-i-like-my-job.aspx</link><pubDate>Fri, 27 Jun 2008 18:14:45 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:109406</guid><dc:creator>dorony</dc:creator><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.microsoft.co.il/blogs/dorony/rsscomments.aspx?PostID=109406</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/06/27/why-i-like-my-job.aspx#comments</comments><description>&lt;p&gt;Recently I&amp;#39;ve been reflecting on my life&amp;#39;s choices. Just a reflective kind of mood, I guess. I chose to become a programmer when I was 18 years old. That was 6.5 years ago, and a pretty young age to make life-changing choices - at least in my country. That choice pretty much set the course for me for the next 9 years, as I was going to study in the university for 3 years and then work in the same place for the following 6 years. That&amp;#39;s a lot of burden on 18-year old shoulders.&lt;/p&gt; &lt;p&gt;So I got to thinking - if I had to make the same decision again, would I choose the same way?&lt;/p&gt; &lt;p&gt;And what I answered myself was - Hell yeah! I love being a programmer, and the main reasons are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;It&amp;#39;s challenging work. I get to use my brain to solve problems.&lt;/li&gt; &lt;li&gt;I get to &lt;em&gt;create &lt;/em&gt;stuff. At first there is nothing, but after some &lt;em&gt;creation &lt;/em&gt;there is something that people can use, and it makes their life easier. Well, most of the time.&lt;/li&gt; &lt;li&gt;I&amp;#39;m no artist, and can barely draw an image of a person without him looking like he just fled Chernobyl, but after writing software I can sometimes look at it and say: &amp;quot;Hey, I just made something pretty&amp;quot;.&lt;/li&gt; &lt;li&gt;I get to work with some really smart people, and learn from them.&lt;/li&gt; &lt;li&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/dorony/archive/2007/02/12/The-Bug-and-You.aspx"&gt;I get to learn so much about myself, as a person&lt;/a&gt;. Debugging one of these random-looking bugs can really tell you what you&amp;#39;re made of.&lt;/li&gt; &lt;li&gt;The pay isn&amp;#39;t bad.&lt;/li&gt; &lt;li&gt;I&amp;#39;m pretty good at it, or so I&amp;#39;d like to think.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;It&amp;#39;s hard work, but I guess I wouldn&amp;#39;t have it any other way. I can&amp;#39;t really think of anything else I would have preferred to do. I like to write, but I don&amp;#39;t think I could have done it full-time as a reporter. Blogging pretty much scratches that itch for me.&lt;/p&gt; &lt;p&gt;Speaking of scratching itches, if only I could write some software that killed all mosquitos, I&amp;#39;d be a much happier person now. Probably richer too. The bastards are driving me crazy.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=109406" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Miscellaneous/default.aspx">Miscellaneous</category><category domain="http://blogs.microsoft.co.il/blogs/dorony/archive/tags/Development/default.aspx">Development</category><feedburner:origLink>http://blogs.microsoft.co.il/blogs/dorony/archive/2008/06/27/why-i-like-my-job.aspx</feedburner:origLink></item></channel></rss>
