tag:blogger.com,1999:blog-4256794073853286202024-03-14T19:33:24.031+01:00Frank Bakker talks about software developmentHow great teams can create great solutionsFrank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-425679407385328620.post-85312415442572181972015-11-24T22:26:00.000+01:002015-11-25T13:08:38.229+01:00Find code patterns using C# and Roslyn: Introducing IntelliFindSince the beginning of time, code editors have been equipped with ‘Find’ and / or ‘Find All’ features. This allows the user to search for any or all occurrences of literal text in a code base. Most editors also allow you to use regular expressions for more ‘advanced’ searches.<br>
<br>
But what if you need to search for all variables with the name ‘goldCustomer’, because someone decided these need to be renamed to ‘specialCustomer’. Or search for methods with a set of tree parameters named “name”, “dateOfBirth” and "address”, because these need to be refactored to use a new Person class. Or your codebase is filled with another repeating pattern that seemed to be a good idea to someone at one point, but now hinders development big time. These kind of searches are not easily done with simple text search or regular expressions. You need a search tool that understands the syntax of your code in order to search for these kinds of patterns.<br>
<br>
Fortunately we now have the Roslyn compiler engine that understands the structure of C# code and exposes this structure in the form of syntax trees. You can use these syntax trees to analyze code by creating custom analyzers like I did <a href="http://blog.frankbakker.net/2015/09/c-string-interpolation-best-practices.html">here</a>. For ad-hoc searches in day to day work however writing a custom analyzer for one time use is just way to much work. It involves creating a new solution in a new visual studio instance, writing the code for the analyzer, debugging it in the experimental Visual Studio Instance and then install it into yet another instance in order to search your target code base. It would be nice if we could simplify this.<br>
<a href="http://blog.frankbakker.net/2015/11/find-code-patterns-using-c-and-roslyn.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-33761353398404376632015-09-26T03:48:00.000+02:002015-09-29T08:51:03.140+02:00Creating a Roslyn code fix for Interpolated Strings in C#In my <a href="http://blog.frankbakker.net/2015/09/c-string-interpolation-best-practices.html" target="_blank">previous post</a> I showed a possible pitfall with the new C# string interpolation feature. I also showed how I created a Roslyn code analyzer to find these possible problems. As promised I will now follow up with the code fix provider that will help save you some typing when this analyzer fires a diagnostic message. Along the way I hope to show that creating code fixes is not as complicated as it might look.
<div>
<br></div>
<div>
So our goal is that if we get a diagnostic warning like</div>
<div>
<br></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9GlVbpFWqS4kzRaLoR9PUE5O2pHuhOVAEVPcPydoL5gLMbu-pgFFPfi2d65B7Dx3KKjtHJDDQAEolU_rqT6pNqgAkvahqSQQY6eGUlFebauZazGhgcVChKvMq8sv2oJ4dbRHTgYf379U/s1600/Squiggle.png" imageanchor="1"><img border="0" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9GlVbpFWqS4kzRaLoR9PUE5O2pHuhOVAEVPcPydoL5gLMbu-pgFFPfi2d65B7Dx3KKjtHJDDQAEolU_rqT6pNqgAkvahqSQQY6eGUlFebauZazGhgcVChKvMq8sv2oJ4dbRHTgYf379U/s640/Squiggle.png" width="640"></a>
<br>
<pre class="cscode"></pre>
<div>
we would like our code fix to replace it with something like:</div>
<div>
<br></div>
<div>
<pre class="cscode"><code><span class="key">var</span> today = DateTime.Today;
WriteLine(Invariant($<span class="str">"The date is {today}"</span>));
</code></pre>
<div>
<br>
Because I used the 'Analyser With Code Fix' template when creating the solution, I also got a CodeFixProvider into my solution to start with. This is the class where we will be fixing the code by adding the call to Invariant around the interpolated string.
<br>
</div></div></div><a href="http://blog.frankbakker.net/2015/09/creating-code-fix-for-interpolated.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-31593350252266096402015-09-03T22:31:00.000+02:002015-09-04T12:56:34.930+02:00C# String Interpolation best practicesIn this post I will show you my thoughts on using the new C# string interpolation syntax with regard to formatting. I will try to define a best practice for using this new feature and then show how I created a Roslyn based code analyser that checks for this best practice.<br>
<br>
Last week a colleague of mine showed us how he used the new C# String Interpolation feature in his project.<br>
<br>
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"><span style="color: blue;">var</span> requestUri = $<span style="color: #a31515;">"api/v1/Colors/{id}/Variants"</span>;
</code></pre>
<br>
which is equivalent to
<br>
<br>
<pre style="background-color: white; margin: 0em; overflow: auto;"><code style="color: black; font-family: Consolas,"Courier New",Courier,Monospace; font-size: 10pt;"><span style="color: blue;">var</span> requestUri = <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"api/v1/Colors/{0}/Variants"</span>,id);</code></pre>
<br>
I responded that I like the new syntax, but the downside is that it uses the CurrentCulture of the executing thread as the FormatProvider. This makes the behaviour of this code dependant on the thread context which may lead to unexpected results. <a href="http://blog.frankbakker.net/2015/09/c-string-interpolation-best-practices.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-26721641483591194582015-09-03T13:15:00.000+02:002015-09-03T13:48:32.620+02:00RebootOk, let's state the Obvious: It has been a long time since I wrote a blog post. I have just finished transferring my old content to my new blog: <a href="http://blog.frankbakker.net/" target="_blank">Frank Bakker talks about software development</a>. This way everything will stay together in a single archive.<br />
I have recently started a new job at <a href="http://www.avivasolutions.nl/" target="_blank">Aviva Solutions</a>. At Aviva I will be doing what I love to do most: Help customers solve their complex problems by creating high quality software solutions with a team of highly skilled professionals. <br />
For me this new start is a good opportunity to pick up blogging again. Writing a blog forces me to organize my thoughts about a subject in a way you can understand it. I hope this result in both you and me learning something new.Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com1tag:blogger.com,1999:blog-425679407385328620.post-14150007150619309412009-11-12T22:23:00.000+01:002015-09-08T10:17:50.179+02:00New coordination datastructures in .Net 4.0 Beta 2To be honest a have not spent too much time looking at .Net 4.0 beta 2 yet. But I do keep up with the <a href="http://blogs.msdn.com/pfxteam/default.aspx" title="blogs">blogs</a> concerning Parallel Extensions. Josh Philps has just <a href="http://blogs.msdn.com/pfxteam/archive/2009/11/06/9918363.aspx" title="Posted">posted</a> an entry about the changes that were made in the Coordination Data Structures (CDS) in Beta 2. The CDS are the types that have been added to the framework that will help writing concurrent applications without having to do (to much of) your own synchronization. I used two of the CDS classes (ConcurrentDictionary<Tkey, TValue> and Lazy<T>) in the CacheDictionary that I wrote about in <a href="http://blogs.infosupport.com/blogs/frankb/archive/2008/12/31/Implementing-a-Thread-Safe-cache-using-the-Parallel-Extensions.aspx" title="this">this</a> article.<br>
<br>
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.5%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">class</span></span> CacheDictionary<TKey, TValue> </pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">where</span></span> TValue : <span style="color: blue;"><span style="background-color: #f4f4f4;">class</span></span> <span style="color: green;"><span style="background-color: #f4f4f4;">// needs to be a ref type due to current limitation of lazyInit<> </span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 3:</span></span> { </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 4:</span></span> ConcurrentDictionary<TKey, LazyInit<TValue>> _cacheItemDictionary = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> ConcurrentDictionary<TKey, LazyInit<TValue>>(); </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 5:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 6:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> TValue Fetch(TKey key, Func<tvalue> producer) </tvalue></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 7:</span></span> { </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 8:</span></span> LazyInit<tvalue> cacheItem; </tvalue></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 9:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span> (!_cacheItemDictionary.TryGetValue(key, <span style="color: blue;"><span style="background-color: #f4f4f4;">out</span></span> cacheItem)) </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 10:</span></span> { </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 11:</span></span> cacheItem = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> LazyInit<tvalue>(() => producer(), LazyInitMode.EnsureSingleExecution); </tvalue></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 12:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 13:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span> (!_cacheItemDictionary.TryAdd(key, cacheItem)) </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 14:</span></span> { </pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 15:</span></span> <span style="color: green;"><span style="background-color: #f4f4f4;">// while we never remove items, if TryAdd fails it should be present </span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 16:</span></span> cacheItem = _cacheItemDictionary[key]; </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 17:</span></span> } </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 18:</span></span> } </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 19:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">return</span></span> cacheItem.Value; </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 20:</span></span> } </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 21:</span></span> } </pre>
</div>
</div>
<br>
<a href="http://blog.frankbakker.net/2009/11/new-coordination-datastructures-in-net.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-87527989235888779222009-03-17T21:26:00.000+01:002015-09-08T10:20:02.844+02:00Visualizing Linq operators: The Info Support Linq Posters<br>
Over the last few months I have been working on a little project to make Linq ‘come to life’ in two full size posters that developers can hang on the wall of their offices. The Linq posters demonstrates the usage of all Linq operators using visual sequences of female and male figures. Since this week the final result is ready and can be ordered in Print / Downloaded from our website <a href="http://www.infosupport.com/linq" title="http://www.infosupport.com/linq"><span style="color: #669966;">http://www.infosupport.com/linq</span></a> free of charge! <br>
<strong><a href="http://blogs.infosupport.com/wp-content/uploads/archief/4e9c2742c99b02.96301853.jpg"><img alt="poster_staand" border="0" src="http://blogs.infosupport.com/wp-content/uploads/archief/4e9c2742c99b02.96301853.jpg" height="285" style="border-width: 0px;" width="202"></a> <a href="http://blogs.infosupport.com/wp-content/uploads/archief/4e9c27432e2d65.51979931.jpg"><img alt="poster_liggend" border="0" src="http://blogs.infosupport.com/wp-content/uploads/archief/4e9c27432e2d65.51979931.jpg" height="285" style="border-width: 0px;" width="401"></a></strong><br>
<strong>So why create a Linq poster?</strong><br>
<a href="http://blog.frankbakker.net/2009/03/visualizing-linq-operators-info-support.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-35245584116349240202009-03-15T21:29:00.000+01:002015-09-08T10:21:13.108+02:00CacheDictionary for .Net 3.5, using ReaderWriterLockSlim ?In my previous <a href="http://blogs.infosupport.com/blogs/frankb/archive/2008/12/31/Implementing-a-Thread-Safe-cache-using-the-Parallel-Extensions.aspx" target="_blank">post</a> I described how to create a thread safe data cache using PFX. PFX however is scheduled to be <a href="http://blogs.infosupport.com/blogs/frankb/archive/2008/10/16/Parallel-Extensions-for-.Net-Framework-will-be-included-in-.Net-4.0.aspx" target="_blank">released as a part of the .Net framework 4.0</a> which means we will have to wait a while before we can use this in real world applications. That’s why I created an implementation using the generic Dictionary combined with a ReaderWriterLockSlim which are both available in .Net 3.5. today.<br>
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; height: 344px; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.5%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">class</span></span> CacheDictionary<tkey tvalue=""></tkey></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 3:</span></span> ReaderWriterLockSlim _cacheLock = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> ReaderWriterLockSlim();</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 4:</span></span> Dictionary<tkey alue="" lazyinit="">> _cacheItemDictionary = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> Dictionary<tkey alue="" azyinit="">>();</tkey></tkey></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 5:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 6:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> TValue Fetch(TKey key, Func<tvalue> producer)</tvalue></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 7:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 8:</span></span> LazyInit<tvalue> cacheItem;</tvalue></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 9:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">bool</span></span> found;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 10:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 11:</span></span> _cacheLock.EnterReadLock();</pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 12:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">try</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 13:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 14:</span></span> found = _cacheItemDictionary.TryGetValue(key, <span style="color: blue;"><span style="background-color: #f4f4f4;">out</span></span> cacheItem);</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 15:</span></span> }</pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 16:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">finally</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 17:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 18:</span></span> _cacheLock.ExitReadLock();</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 19:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 20:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 21:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span> (!found)</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 22:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 23:</span></span> _cacheLock.EnterWriteLock();</pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 24:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">try</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 25:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 26:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span> (!_cacheItemDictionary.TryGetValue(key, <span style="color: blue;"><span style="background-color: #f4f4f4;">out</span></span> cacheItem))</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 27:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 28:</span></span> cacheItem = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> LazyInit<tvalue>(producer);</tvalue></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 29:</span></span> _cacheItemDictionary.Add(key, cacheItem);</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 30:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 31:</span></span> }</pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 32:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">finally</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 33:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 34:</span></span> _cacheLock.ExitWriteLock();</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 35:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 36:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 37:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 38:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">return</span></span> cacheItem.Value;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 39:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 40:</span></span> }</pre>
</div>
</div>
<br>
<a href="http://blog.frankbakker.net/2009/03/cachedictionary-for-net-35-using.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-21417573444643982132008-12-31T22:32:00.000+01:002015-09-08T10:22:07.793+02:00Implementing a Thread Safe cache using the Parallel ExtensionsCaching objects based on a key is a very common task in software development, making it both thread safe and scalable however is not quite trivial. That's why I implemented a generic implementation of such a cache, to handle the concurrency issues I used the Parallel Extensions to the .NET framework (PFX).<br>
[Update: See <a href="http://blogs.infosupport.com/blogs/frankb/archive/2009/03/15/CacheDictionary-for-.Net-3.5_2C00_-using-ReaderWriterLockSlim-_3F00_.aspx">this post</a> for a cache that works with .Net 3.5 without PFX]<br>
A implementation pattern I have seen quite often, uses a dictionary to store cached items based on a cache key and looks like the following:<br>
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.5%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> Dictionary<<span style="color: blue;"><span style="background-color: #f4f4f4;">int</span></span>, Item> _cachedItems = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> Dictionary<<span style="color: blue;"><span style="background-color: #f4f4f4;">int</span></span>, Item>();</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">object</span></span> _lock = <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">object</span></span>(); </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 3:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 4:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> Item GetItem(<span style="color: blue;"><span style="background-color: #f4f4f4;">int</span></span> id)</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 5:</span></span> { </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 6:</span></span> Item result; </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 7:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span>(!_cacheItems.TryGetValue(id, <span style="color: blue;"><span style="background-color: #f4f4f4;">out</span></span> result)) </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 8:</span></span> { </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 9:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">lock</span></span>(_lock) </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 10:</span></span> { </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 11:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span>(!_cacheItems.TryGetValue(id, <span style="color: blue;"><span style="background-color: #f4f4f4;">out</span></span> result))</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 12:</span></span> { </pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 13:</span></span> result = CreateItem(id); <span style="color: green;"><span style="background-color: #f4f4f4;">// does the actual expensive work of creating the item</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 14:</span></span> _cacheItems.Add(id, result);</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 15:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 16:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 17:</span></span> } </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 18:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">return</span></span> result;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 19:</span></span> }</pre>
</div>
</div>
This implementation uses a pattern known as 'double check locking', this allows for items already in the cache to be retrieved without using a lock, only if the item is not found it acquires a lock, checks again for the item having been added by another thread between checking the first time and acquiring the lock, and then creates the item and stores it for future use.<br>
<a href="http://blog.frankbakker.net/2008/12/implementing-thread-safe-cache-using.html#more">Read more »</a>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-21779487441682800012008-12-11T22:35:00.000+01:002015-08-28T23:04:58.124+02:00F# to ship as part of Visual Studio 2010To be honest I don’t really like to blog about stuff that is already ‘out there’ on the web. There are however some topics that I personally think are important and don’t always get the attention they deserve. These topics mostly concentrate around parallel programming (see my blogroll in the sidebar). So for these topics I will make an exception.<br />
Today Don Syme announced that <a href="http://blogs.msdn.com/dsyme/archive/2008/12/10/fsharp-to-ship-as-part-of-visual-studio-2010.aspx" target="_blank">F# will be released with Visual Studio 2010</a>. I had expected this news to get out at the PDC last October, but for some reason we were kept in the dark a little longer. <br />
I think this is a mayor step in bringing functional programming to mainstream software development. Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-189668507513296892008-12-02T22:38:00.000+01:002015-08-28T23:04:58.118+02:00More context information in Linq queriesLast week I <a href="http://blogs.infosupport.com/blogs/frankb/archive/2008/11/23/Selecting-or-filtering-on-the-sequence-number-in-Linq.aspx" target="_blank">posted</a> on how to use an elements sequence number in Linq queries. In the project I just finished working on, we wrote a lot of Linq queries where we needed even more information related to an elements position in the sequence, like comparing it to the the element that came directly before or directly after it. <br />
To be concrete: the input sequence contains all (ordered) historical versions of the same insurance policy object. From this sequence we need to filter all items for which a specific property has changed since the previous version. This could be implemented like:<br />
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; height: 177px; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.64%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> Version previous = <span style="color: blue;"><span style="background-color: #f4f4f4;">null</span></span>;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 3:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">foreach</span></span> (var version <span style="color: blue;"><span style="background-color: #f4f4f4;">in</span></span> Versions)</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 4:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 5:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">if</span></span> (previous != <span style="color: blue;"><span style="background-color: #f4f4f4;">null</span></span> && previous.amount != version.amount)</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 6:</span></span> {</pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 7:</span></span> <span style="color: green;"><span style="background-color: #f4f4f4;">// do something with this item</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 8:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 9:</span></span> previous = version;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 10:</span></span> }</pre>
</div>
</div>
Once you have gotten addicted to the declarative style of Linq, writing code like this just doesn't cut it anymore. I wanted to be able to use the filtered items as a sequence so it can be used in a Linq query.<br />
Using the pattern I described last week this could be written like <br />
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; height: 49px; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 98.59%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> Versions.select((item, index) => <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> {item, index}).Skip(1)</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> .<span style="color: blue;"><span style="background-color: #f4f4f4;">where</span></span>(v=>Versions.ElementAt(v.index - 1).amount != v.item.amount)</pre>
</div>
</div>
This query finds each items index number and uses it to find the preceding item using the ElementAt() method. This makes it possible to compare each item to it's previous item in the where clause. The Skip(1) is needed because the first element obviously doesn't have a previous item.<br />
The ElementAt() method however is not very efficient, because in most cases to find a single item it iterates the sequence from the begin to the requested item. Finding each item's preceding item by re-looping the sequence again can get you into serious performance issues when using larger sets.<br />
Because I needed this kind of queries a lot in this project, I wanted to make then both easy to write and efficient in execution. So I wrote an extension method I called WithContext() that wraps each input item in a container object, along with some information about its context in the sequence. This allows for the code above to be written as:<br />
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; height: 36px; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.5%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> Versions.WithContext().Where(v=>v.Previous != <span style="color: blue;"><span style="background-color: #f4f4f4;">null</span></span> && v.Previous.Amount != v.Current.Amount)</pre>
</div>
</div>
To select the duration of each version, based on its own StartDate and the StartDate of the next item, I can now write:<br />
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.5%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> Versions.WithContext().Select(v.Next.StartDate - v.Current.StartDate)</pre>
</div>
</div>
WithContext() takes an IEnumerable<t> and returns an IEnumerable<elementwithcontext>>. ElementWithContext is a simple class that provides properties to retrieve the Current item as well as the Previous and the Next. While at it I added properties to get all Preceding and all Following items, as well as the sequence number.</elementwithcontext></t><br />
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; height: 250px; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 97.5%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">class</span></span> ElementWithContext<t></t></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 3:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> T Previous { get; <span style="color: blue;"><span style="background-color: #f4f4f4;">private</span></span> set; }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 4:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> T Current { get; <span style="color: blue;"><span style="background-color: #f4f4f4;">private</span></span> set; }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 5:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> T Next { get; <span style="color: blue;"><span style="background-color: #f4f4f4;">private</span></span> set; }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 6:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">int</span></span> Index { get; <span style="color: blue;"><span style="background-color: #f4f4f4;">private</span></span> set; }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 7:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 8:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> IEnumerable<t> Preceding { get; <span style="color: blue;"><span style="background-color: #f4f4f4;">private</span></span> set; }</t></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 9:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> IEnumerable<t> Following { get; <span style="color: blue;"><span style="background-color: #f4f4f4;">private</span></span> set; }</t></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 10:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 11:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">internal</span></span> ElementWithContext(T previous, T current, T next,</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 12:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">int</span></span> index, IEnumerable<t> preceding, IEnumerable<t> following)</t></t></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 13:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 14:</span></span> Current = current;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 15:</span></span> Previous = previous;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 16:</span></span> Next = next;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 17:</span></span> Index = index;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 18:</span></span> Preceding = preceding;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 19:</span></span> Following = following;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 20:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 21:</span></span> }</pre>
</div>
</div>
The implementation of WithContext() looks a bit like the code in the first sample. It loops the input sequence and for each element it yields a new ElementWithContext. To find the next element I did a kind of 'look ahead' in the for loop. To do this I tweaked the input sequence so that it represents all 'Next' items' . I did this by first adding an empty element at the end (the last item does not have a Next item) and then skip the first item (the first 'next' item is the second in the sequence). This way WithContext() conforms to Linq's 'deferred execution' model by not taking more items from the input then necessary.<br />
<div style="background-color: #f4f4f4; border-image: none; border: 1px solid gray; cursor: text; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; height: 310px; line-height: 12pt; margin: 20px 0px 10px; overflow: auto; padding: 4px; width: 98.61%;">
<div style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; width: 100%;">
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 1:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">static</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">public</span></span> IEnumerable<elementwithcontext>> WithContext<t>(<span style="color: blue;"><span style="background-color: #f4f4f4;">this</span></span> IEnumerable<t> source)</t></t></elementwithcontext></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 2:</span></span> {</pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 3:</span></span> <span style="color: green;"><span style="background-color: #f4f4f4;">// initialize the previous and current item for the first source element</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 4:</span></span> T previous = <span style="color: blue;"><span style="background-color: #f4f4f4;">default</span></span>(T);</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 5:</span></span> T current = source.FirstOrDefault();</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 6:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">int</span></span> index = 0;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 7:</span></span> </pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 8:</span></span> <span style="color: green;"><span style="background-color: #f4f4f4;">// Loop all 'Next' items</span></span></pre>
<pre style="color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 9:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">foreach</span></span> (T next <span style="color: blue;"><span style="background-color: #f4f4f4;">in</span></span> source.Union(<span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span>[] { <span style="color: blue;"><span style="background-color: #f4f4f4;">default</span></span>(T) }).Skip(1))</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 10:</span></span> {</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 11:</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">yield</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">return</span></span> <span style="color: blue;"><span style="background-color: #f4f4f4;">new</span></span> ElementWithContext<t>(previous, current, next,</t></pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 12:</span></span> index, source.Take(index), source.Skip(index + 1));</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 13:</span></span> </pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 14:</span></span> previous = current;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 15:</span></span> current = next;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 16:</span></span> index++;</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 17:</span></span> }</pre>
<pre style="background-color: #f4f4f4; color: black; font-family: consolas, "Courier New", courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; width: 100%;"><span style="color: #606060;"><span style="background-color: #f4f4f4;"> 18:</span></span> }</pre>
</div>
</div>
One more item that I'll keep handy on my personal utility belt <img alt=":-)" class="wp-smiley" src="http://blogs.infosupport.com/wp-includes/images/smilies/simple-smile.png" style="height: 1em; max-height: 1em;" /> <br />
Oh, and thanks to <a href="http://blogs.infosupport.com/ernow/default.aspx" target="_blank">Erno</a> for pointing me to this Live Writer <a href="http://gallery.live.com/liveItemDetail.aspx?li=d4409446-af7f-42ec-aa20-78aa5bac4748&l=8" target="_blank">Add-In</a> for the code snippets. I hope this helps reading these way to long code samples (sorry for that).Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-14109048264046802012008-11-23T22:40:00.000+01:002015-08-28T23:04:58.111+02:00Selecting or filtering on the sequence number in LinqA few weeks ago I was writing a Linq query where I needed each items sequence number (or index) as a part of the filter expression in a Where operation. To simplify the actual problem let's say I needed to filter out only the odd items. One (wrong) way to do this would be:<br />
int i = 0;<br />
var filtered = input.Where(x => i++ % 2 == 1);<br />
This will appear to work at first but it only works correct the first time the filtered sequence is iterated. I will not get into this to deep here, but it has to do with the lambda updating the outer variable which is a bad idea.<br />
Fortunately there is a correct (and easier) way to do this. As it turns out the Where extension method has an extra overload that excepts a lambda function with two input parameters. When you use this overload the lambda receives an extra input parameter which indicates the sequence number of the current item. The correct code looks like this.<br />
var filtered = input.Where((x, i) => i % 2 == 1);<br />
As I wanted to write the rest of the query in Linq comprehension syntax (yes it does have some advantageous sometimes), I wanted to write something like<br />
<span style="font-family: "Courier New", Courier, monospace;">var filtered = from x in input</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> // other Linq stuff </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> where ???? % 2 == 1</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> select x;</span><br />
Comprehension syntax however does not have a built in way to refer to the sequence number (as far as I could find out in 15 min with Google). Bummer <img alt=":-(" class="wp-smiley" src="http://blogs.infosupport.com/wp-includes/images/smilies/frownie.png" style="height: 1em; max-height: 1em;" /><br />
I did find that the Select method has an overload just like the Where method, that accepts a lambda with a sequence number parameter. This allows the sequence number to be used in the query's output.<br />
var withSequenceNumber = input.select((item, index) => new {item, index})<br />
Just like in the where clause, it is not possible to use the sequence number in comprehension syntax's select clause. It is however possible to mix normal C# syntax and comprehension syntax and make the sequence number available to all the comprehension syntax operators:<br />
<span style="font-family: "Courier New", Courier, monospace;">var filtered = from x in input.select((item, index) => new {item, index})</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> // other Linq stuff </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> where x.index %2 == 1</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> select x.item;</span><br />
By first selecting each item along with its sequence number into an anonymous type, the rest of the query can refer to the sequence number as x.index and the item itself as x.item. As an extra bonus the original sequence numbers of the items before filtering are still available after filtering, so they could be used in the select clause to be presented in the ouput.Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-36229108228059756022008-10-16T22:43:00.000+02:002015-08-28T23:04:58.130+02:00Parallel Extensions for .Net Framework will be included in .Net 4.0I has been a while since I wrote a <a href="http://blogs.infosupport.com/blogs/frankb/archive/2007/07/29/Will-multi_2D00_core-processing-change-the-way-we-write-software_3F00_.aspx" target="_blank">post</a> on parallel programming. Since that time a lot has happend in field of parallel programming.<br />
Microsoft has been working hard on implementing the Parallel Extensions for .Net Framewok (PFX) and has now anounced that it will be a core part of the next version of the .Net Framework (right into mscorlib.dll). See the post on the PFX blog <a href="http://blogs.msdn.com/pfxteam/archive/2008/10/10/8994927.aspx" target="_blank">PFX blog </a>. If you are interested in Parallel programming I strongly recomend reading up on the PFX blog. I also expect more details to be anounced at the upcoming PDC (to bad I won't be there).<br />
FPX includes a task scheduler that promisses to scale well beyond two of four CPU's / cores and allowes LINQ to objects queries to be executed parallel (PLINQ). The later, and probably lesser known aditions include so called Coordination Data Structures (CDS) these include thread safe collection classes, like stacks an queues. One of my personal favorites of the CDS is LazyInit<t>. LazyInit is a smart little helper class that makes it easy to implement Lazy Initialization of fields or local variables, of course this is done thread safe so that it can be used in parallel scenario's.</t><br />
Can't wait to use these new goodies in real life projects!Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-72511084858288452702008-06-06T22:45:00.000+02:002015-08-28T23:04:58.152+02:00More fun with Extension Methods and Lambda’s: Creating a generic tree visitorOne of the most common data structures in Software Engineering is the tree. In the .Net framework for instance you can find them in the file system, the controls of a win-forms application, nodes in an XML document etc.<br />
A common task with trees is to traverse all nodes to look for a specific node or perform an operation on each node. This is usually called visiting. Many tree like data structures unfortunately don't have a built-in visiting mechanism, so we usually need to build this ourselves with something like a recursive method.<br />
What I wanted to do is to write an generic implementation to visit any recursive tree. While the basic algorithm to do this is not very complicated, there are two factors that make it difficult to make the implementation generic, the first is that the type of the nodes is different for each tree, the second is that the way to obtain the children of a node is different for each tree. C# 2.0 solved the first problem with generics, and now C# 3.0 has solved the second problem with Lambda expressions.<br />
A generic tree visitor should allow me to iterate all nodes as a single Enumerable<t>, which of course has the advantage that it can be used it a foreach or a Linq query. So the code I Would like to write to visit a tree would be something like the following:</t><br />
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> node <span style="color: blue;">in</span> root.VisitDepthFirst(n => n.GetChildNodes()))</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: green;">// …</span></span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">}</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"></span><br /></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
</div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
Where VisitDepthFirst is a generic extension method that operates on the root object. The extension method receives a Lambda expression that is used on a node to retrieve all it's children. For most trees this is a single property or method which return a collection of all child objects.</div>
See the implementation of the depth first visitor below<br />
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;">static</span> <span style="color: blue;">public</span> <span style="color: #2b91af;">IEnumerable</span><t> VisitDepthFirst<t>(<span style="color: blue;">this</span> T root, <span style="color: #2b91af;">Func</span><t span="" style="color: #2b91af;">IEnumerable</t></t></t></span><t>> childSelector)</t></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">if</span> (root == <span style="color: blue;">null</span>) <span style="color: blue;">yield</span> <span style="color: blue;">break</span>;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: green;">// we return the root</span></span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">yield</span> <span style="color: blue;">return</span> root;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"></span><br /></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: green;">// then we do a recursive Depth first search of all children and yield each item we find</span></span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> child <span style="color: blue;">in</span> childSelector(root).SelectMany(c => c.VisitDepthFirst(childSelector)))</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">yield</span> <span style="color: blue;">return</span> child;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>}</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">}</span></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri; font-size: small;"></span><br /></div>
When testing this in a Win-forms application I first tried the following<br />
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> control <span style="color: blue;">in</span> groupBox2.VisitDepthFirst(c => c.Controls))</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>control.Text = <span style="color: #a31515;">"Done"</span>;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">}</span></div>
This however leads to a a few compiler errors. The first is has to do with the fact that groupBox2 is of type <span style="color: #2b91af;"><span style="font-family: Courier New;">GroupBox </span></span>and not <span style="color: #2b91af;"><span style="font-family: Courier New;">Control </span></span>therefore the compiler expects the Lambda expression to return <span style="color: #2b91af;"><span style="font-family: Courier New;">IEnumerable</span></span><<span style="color: #2b91af;"><span style="font-family: Courier New;">GroupBox </span></span>> instead of <span style="color: #2b91af;"><span style="font-family: Courier New;">IEnumerable</span></span><<span style="color: #2b91af;"><span style="font-family: Courier New;">Control</span></span>>. The second problem is that the ControlsCollection does not implement a generic <span style="color: #2b91af;"><span style="font-family: Courier New;">IEnumerable<> </span></span>at all but in stead only the non-generic <span style="color: #2b91af;"><span style="font-family: Courier New;">IEnumerable</span></span>.<br />
To fix this I had to be a bit more explicit about the type of the node and use Linq's Cast<>() Extension method to convert the Controls collection to <span style="color: #2b91af;"><span style="font-family: Courier New;">IEnumerable</span></span><<span style="color: #2b91af;"><span style="font-family: Courier New;">Control</span></span>>. The following is the correct way to do this.<br />
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> control <span style="color: blue;">in</span> groupBox2.VisitDepthFirst<<span style="color: #2b91af;">Control</span>>(c => c.Controls.Cast<<span style="color: #2b91af;">Control</span>>()))</span><span style="font-family: "Courier New"; font-size: 10pt;">{</span><span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>control.Text = <span style="color: #a31515;">"Done"</span>;</span><span style="font-family: "Courier New"; font-size: 10pt;">}</span><br />
Likewise visiting all nodes in an xml document is done as follows<br />
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;">foreach</span> (<span style="color: #2b91af;">XmlNode</span> childNode <span style="color: blue;">in</span> xmlDocument.VisitDepthFirst<<span style="color: #2b91af;">XmlNode</span>>(n => n.ChildNodes.Cast<<span style="color: #2b91af;">XmlNode</span>>()))</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"></span><br /></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">}</span></div>
To be complete I also created a breath-first search. I don't know if I'll ever use it, but why not.<br />
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;">static</span> <span style="color: blue;">public</span> <span style="color: #2b91af;">IEnumerable</span><t> VisitBreathFirst<t>(<span style="color: blue;">this</span> T root, <span style="color: #2b91af;">Func</span><t span="" style="color: #2b91af;">IEnumerable</t></t></t></span><t>> childSelector)</t></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span style="color: blue;"> if</span> (root == <span style="color: blue;">null</span>) <span style="color: blue;">yield</span> <span style="color: blue;">break</span>;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"></span><br /></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: #2b91af;">Queue</span><t> open = <span style="color: blue;">new</span> <span style="color: #2b91af;">Queue</span><t>(); </t></t></span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: green;">// the open queue contains the items that have already been visited, but who's children have not</span></span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="color: green; font-family: "Courier New"; font-size: 10pt;"></span><br /></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">yield</span> <span style="color: blue;">return</span> root;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>open.Enqueue(root);</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">while</span> (open.Count >0)</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>T item = open.Dequeue();</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span> </span><span style="color: blue;">foreach</span> (T child <span style="color: blue;">in</span> childSelector(item))</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>{</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span><span style="color: blue;">yield</span> <span style="color: blue;">return</span> child;</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>open.Enqueue(child);</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>}</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;"><span> </span>}</span></div>
<div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;">
<span style="font-family: "Courier New"; font-size: 10pt;">}</span></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri; font-size: small;"></span><br /></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri; font-size: small;">While I think this is a nice example of generics and Lambda's, I have to be hones that I'm not quite sure if this should have been implemented as Extension Methods. The problem here is that these extension methods operate on any object without restriction, which makes them pop up in intellisense all over the place once you add the using directive. The alternative ofcource is to make it a normal static method and loose the syntactic sugar of extension methods. </span></div>
<div class="MsoNormal" style="margin: 0in 0in 10pt;">
<span style="font-family: Calibri; font-size: small;">Any comments on that one?</span></div>
Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-12330813055502852752008-02-02T22:47:00.000+01:002015-08-28T23:04:58.108+02:00Using C# 3.0 Extension methods and Lambda expressions to avoid nasty Null ChecksIn the project I am currently working on we use a domain model with a quite deep nested structure of classes, code like the following is quite common.<br />
<span style="font-family: "Courier New", Courier, monospace;">// do something with the Adress<br />Console.Writeline(Contract.Parties.Client.Adress.Street);</span><br />
The problem with this is that not all Contacts have a related Parties object and if we do have a Parties object sometimes the Client object is Null. This lead to writing a lot of code code like the following:<br />
<span style="font-family: "Courier New", Courier, monospace;">if (Conract != Null && <br /> Contract.Parties != null && <br /> Contract.Parties.Client != null && <br /> Contract.Parties.Client.Adress != null)<br />{<br /> // do something with the Adress<br /> Console.Writeline(Contract.Parties.Client.Adress.Street);<br />}</span><br />
There are a few problems with this code, the first of which is that it is quit verbose. Second it evaluates the same properties over and over again. In order to reduce the double work we could introduce some extra local variables and create a separete if statement for every step, this will make it even more verbose than it is allready.<br />
Of course C# 3.0 has a lot of new syntax tricks, like extension methods, lambda expression and type inference. I had seen some nice examples (mostly Linq related) but had not been using these features to the max myself. Somehow I got the idea that these features would help me solve the Null checking problem.<br />
I figured that the code I wanted to write was something like the following.<br />
<span style="font-family: "Courier New", Courier, monospace;">if (Contract<br /> .NullSafe(c => c.Parties)<br /> .NullSafe(p => p.Client)<br /> .NullSafe(c => c.Address) != null)<br />{<br /> // do something with the adress<br /> Console.Writeline(Contract.Parties.Client.Adress.Street);<br />}</span><br />
The idea is that all parts of the path are expressed in separate lambda expressions which are chained together. If any link in the chain returns null, the rest of the path is never evaluated and the result of the whole expression will also be null.<br />All I had to do to make this possible was write one single extension method that would operate on any object, I was quite amazed that I could do this with verry little code that, besides some generic stuff, was actually quite simple.<br />
<span style="font-family: "Courier New", Courier, monospace;"> public static TResult NullSafe<t tresult="">(this T target, Func<t tresult=""> func)<br /> {<br /> if (target != null)<br /> return func(target);<br /> else<br /> return default(TResult);<br /> }</t></t></span><br />
All the generics make it look a lot more complicated than it actually is. This extension method receives two arguments, the first of which is the object it operates on and the second is a generic Func<t tresult=""> delegate (the lambda expression). The return type of the extension method is automatically inferred from the return type of the lambda that is passed in. This allows you to call NullSafe again on the result of the first call and use IntelliSense to type p.Client in the second lambda.<br />The nice thing about extension methods is, besides that they can operate on any existing class without changing it, that they can also operate on Null references without causing a NullReferenceException!! This makes it possible to test for null <strong>inside</strong> the extension method. If the object it is called on is not null it evaluates the lambda expression and returns the result. Otherwise it returns the default value of the expected return type, for reference types this is Null.<br />To make life even better I created another overload of NullSafe that was even simpler</t><br />
<span style="font-family: "Courier New", Courier, monospace;"> public static void NullSafe<t>(this T target, Action<t> action)<br /> {<br /> if (target != null)<br /> action(target);<br /> }</t></t></span><br />
Instead of a generic Func<t tresult=""> delegate this one receives a Generic Action<t> delegate and returns void.<br />This removes the need to retype the whole path inside the if, it actually removes the if altogether.</t></t><br />
<span style="font-family: Georgia, "Times New Roman", serif;">Contract<br /> .NullSafe(c => c.Parties)<br /> .NullSafe(p => p.Client)<br /> .NullSafe(c => c.Address)<br /> .NullSafe(a =><br /> {<br /> // do something with the adress<br /> Console.Writeline(a.Street);<br /> });</span><br />
To bad for me, my current project is still on C# 2.0 so I'll keep doing it old school style <img alt=":-(" class="wp-smiley" src="http://blogs.infosupport.com/wp-includes/images/smilies/frownie.png" style="height: 1em; max-height: 1em;" /><br />
<strong>Exercise</strong><br />
If you would also like some practice with C# 3.0, I would like challenge you to write something that allows me to do the same thing for IEnumerable<t>, I would like to write something like the following </t><br />
<span style="font-family: "Courier New", Courier, monospace;">foreach (Order order in Contract<br /> .NullSafe(c => c.Parties)<br /> .NullSafe(p => p.Client)<br /> .NullSafe(c => c.Orders)<br /> {<br /> // do something with order<br /> Console.Writeline(o.Amount);<br /> }</span><br />
Where Client.Orders is of type IEnumerable<order>. The idea is that I want to iterate every Order in Contract.Parties.Client.Orders. If at any stage in the path (including the Orders collection) we encounter a Null reference we will just loop an empty enumerator and do nothing.</order>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-52451798054508358522007-07-29T22:50:00.000+02:002015-08-28T23:04:58.145+02:00Will our current programming model survive multi-core hardware?<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">For years the innovations of CPU's have been focused on increasing the speed at which a single sequence of instructions gets executed (mainly by increasing the clock frequency). In the last years this trend is changing from increasing sequential execution speed to parallel execution (multi CPU / hyper-threading / multi core). If this trend continues the number of processor cores will no longer be measured in dual or quad, but in K, M or G.<strong></strong></span><br />
<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">Today's popular programming languages (both OO as procedural) encourage (or force) us to write software as a sequence of statements that get executed in a specific order. This paradigm is called an execution thread and it maps very nicely on the traditional CPU model which has a single instruction pointer. Executing tasks in parallel is made possible by calling a system API that creates a new execution thread. This is more a platform than a language feature, which requires even more system API's to do the required locking and synchronization.</span><br />
<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">Generally multi threading is considered an advanced and error prone feature. This is why it is generally used only in situations where parallel execution is an explicit requirement, like in server processes to handle multiple client requests and in GUI applications to allow background processing while the UI keeps handling user events. In situations where tasks <strong><span style="font-family: "Arial","sans-serif";">could</span></strong> be executed parallel, but there is no direct need to do so, we usually stick to our traditional sequential programming model. This is a great waste of the hardware’s parallel processing ability</span><br />
<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">My personally experience to non-sequential languages is pretty much limited to SQL and XSLT. Maybe it is time to spread the horizon and take a look at some of the modern Functional languages like </span><span style="font-family: "Arial","sans-serif"; font-size: 10pt;"><a href="http://research.microsoft.com/fsharp/fsharp.aspx"><span lang="EN-US">F#</span></a></span><span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;"> and </span><span style="font-family: "Arial","sans-serif"; font-size: 10pt;"><a href="http://fortress.sunsource.net/" title="Fortress"><span lang="EN-US">Fortress</span></a></span><span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">. Who is with me?</span>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-61163538387968722712007-04-28T22:52:00.000+02:002015-08-28T23:04:58.149+02:00Lack of support for generic base classes in Windows Forms designerJust recently having started my first real life .Net 2.0 project I wanted to utilize all the cool new features in my day-to-day job. One of those features is of course the support for Generics in C#. But, as with all cool stuff, getting your hopes up to high can get you disappointed.<br />
In our Windows forms application we use a design pattern in which a UserControl defines a callback interface which is implemented by a mediator. This makes sure we have a loose coupling between the UserControl and the source of the rest of the application.<br />
To avoid having a lot of duplicate code I decided to make a base class that does some of the stuff related to initializing the mediator. While every control will have a different mediator interface this called for generics (sample code is written by hand, so don't mind the compiler errors).<br />
class ViewControlBase : UserControl <tmediator><br /> where TMediator : IMediator<br />{<br /> TMediator _mediator;</tmediator><br />
protected TMediator Mediator<br />
{<br />
get { return _mediator; }<br />
}<br />
public InitMediator(IMediator mediator)<br />
{<br />
_mediator = (TMediator) mediator;<br />
// some more generic stuff<br />
}<br />
}<br />
Now the viewControls are derrived from ViewControlBase like this<br />
class CustomerView : ViewControlBase<icustomermediator><br />{<br /> // … Use typed access to the Mediator property<br />}</icustomermediator><br />
By using a generic base I was able to have Typed access to the Mediator in all the derived classes, and I avoided writing the initialization code over and over again. Hitting F5 proved all worked just as expected.<br />
But when I opened one of the ViewControls in the designer the designer was filled with an error saying something was wrong. Usually this means that you have to rebuild the solution, clean up, rebuild some more and eventually it works. Not is time <img alt=":-(" class="wp-smiley" src="http://blogs.infosupport.com/wp-includes/images/smilies/frownie.png" style="height: 1em; max-height: 1em;" /> <br />
The error stated that the class CustomerView was not 'Designable' because it was not able to create an instance of ViewControlBase. That is true, it is however possible to create an instance of ViewControllerBase<tmediator></tmediator><br />
I found a work-around (or a dirty Hack) by creating an empty dummy class like this<br />
class CustomerView : CustomerViewDummy<br />
{<br />
//…<br />
}<br />
class CustomerViewDummy: ViewControlBase<icustomermediator><br />{}</icustomermediator><br />
Now CustomerView is no longer (directly) derived from a generic class the designer stops complaining and shows the control in design view as expected. Since I didn't really like this solution I went back to old-school and duplicated the same code in every control (Bummer!)Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-47569859875543029532007-03-22T21:53:00.000+01:002015-08-28T23:04:58.141+02:00Timezone aware DateTime stucture in .Net 2.0 ?<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">The last year and a half I have been working on a project based on .Net framework 1.1, that (among other things) involved handling multiple time zones. If you have ever worked on such a project you either did it wrong without knowing or you have spent a whole lot of time getting it nearly 100% right. The biggest problems are the XML serialization that always assumes en DateTime represents local time, and the lack of a specific Date-only data type which is time zone independent. When it comes to handling DateTimes in different time zones .Net framework 1.1 just doesn't cut it.</span><br />
<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">Framework 2.0 brings partly good news, only last week I happened to 'intellisense' over a new property on the DateTime structure; DateTime.Kind. It seems that Microsoft has found a use for 2 unused bits in the 64 bits that hold up the data for a DateTime structure. These 2 bits were not enough to store the actual UTC offset. Instead they choose for three possible values, Local, UTC and Unknown. This is a big improvement because it solves the incorrect XML serialization problem of UTC DateTimes. </span><br />
<span lang="EN-US" style="font-family: "Arial","sans-serif"; font-size: 10pt;">The lack of the actual UTC offset in the DateTime structure still has the downside of not being able to handle time zones other than UTC or your own (the one configured in the regional settings) without storing the offset in a separate field and doing your own transformations. Of course the DateTime being a structure which cannot be inherited from doesn't really help to create a generic solution for this one. Second it causes an ambiguity in the hour in the fall when the clock shifts to daylight saving time. This can cause an UTC time being converted to local and back to UTC not to be the same as the original. Last time this happened some of our unit tests broke because the daily build cycle runs exactly within this hour.</span>Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-81633213837992582022007-02-19T22:55:00.000+01:002015-08-28T23:04:58.159+02:00SQL Server 2005 vs. Office Web ComponentsLast week I installed SQL Server 2005 Developer Edition on a development PC. This took almost as long as installing an Oracle server, which is not what I am used to when running a 'routine' SQL Server Setup.<br />
The SQL 2005 installer starts off with a check for all the prerequisites, and all lights were green. I choose an allmost default install of the client tools and the SQL instance itself. When half way installing the required components I got a message that I had a previous version of the 'Office Web Components' (OWC) installed. I needed to remove this previous installation and restart the setup of SQL Server. Bummer.<br />
Checking the 'Add / Remove programs' applet I found that there was indeed a OWC XP version installed, after choosing 'Remove' and clicking through the dialogs I was ready for a retry. Starting up de SQL server setup again choosing the same options as before, all lights green again and …. 'a previous version of OWC is found, please uninstall and redo all the stuff you did twice before ….grrrrr.<br />
Once again I fired up the add / Remove programs and found that now OWC 2003 was installed. Again I uninstalled it, did a reboot for safety and restarted the SQL Server Setup. What do you know… again the same message.<br />
For the third time (of the forth I forgot the actual count) I uninstalled OWC from the Add / Remove programs applet and immediately after removing it I reopened the Add / Remove programs and It was still there!! Even after another reboot, uninstall etc etc the Add remove programs still showed OWC 2003 installed.<br />
As a last resort I located the OWC11.msi on the SQL Server 2005 CD and reinstalled it directly from there. After this I was able to to re-run the SQL Server setup with no problem.Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-76487707260379736002006-10-27T22:56:00.000+02:002015-08-28T23:04:58.155+02:00Show source file and line number information in your Stack tracesA while ago I wrote a blog-post about not breaking the stack trace while throwing an exception up the call stack. Stack traces are the very first place you look when finding the cause of an unexpected exception. Today I was once again saved by a stack trace. A project I am currently working on is starting a pilot in Cairo next week and had some trouble with a NullRefrenceException that was blocking one of the main scenarios. The entire pilot should be called-off, if this didn't get fixed right away.<br />
Luckily the application's crash screen did not only allow me to view the exceptions stack trace (which is pretty common), but we had also deployed the compilers .PDB files along with the application's assemblies. PDB files contain (among other things) information about which IL-instruction corresponds to which source file and line number. The Visual Studio debugger uses this to place the yellow arrow at the next line of code that will be executed. Because most people don't debug on their production environment why should you deploy these files? By default Visual Studio doesn't even generate them for a Release build.<br />
Besides assisting the debugger, the information in the .PDB files are also used at runtime when you call the Exception.ToString() method. At each level in the stack trace after the name of the executing method, the source file and the line number of the executing statement are added, if a PDB file is present for the assempley containing the method. This looks something like this.<br />
<span style="font-size: x-small;"></span><span style="font-size: x-small;">System.NullReferenceException: Object reference not set to an instance of an object.<br /> at Demo.Class1.Foo(Object parameter) in c:\projects\Demo\class1.cs:line 48 <br /> at Demo.Class1.Main(String[] args) in c:\projects\Demo\class1.cs:line 21</span><br />
<span style="font-size: x-small;"></span><span style="font-size: x-small;"></span> <span style="font-size: x-small;"></span><br />
With this information I retrieved the correct version of the source file from source control (of course we label the sources with the build-number in our build cycle) and scrolled to the line number I had found in the stack trace. This showed me the exact statement that caused the NullReferenceException in less than five minutes, without having to reproduce the error in the development environment (which would have been quite tricky in this case). By only looking at the code I was able to see that someone had made a configuration error while installing the pilot environment. Correcting the configuration error fixed the problem and the pilot was ready to go. So unless you have good reasons to hide information about your source code from your end users, you should always set the compilers 'Generate Debugging Information' option to true for Release builds and keep the PDB files along side the assemblies wherever they go.Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-4464085399050324672006-09-29T22:57:00.000+02:002015-08-28T23:04:58.133+02:00Peek into the database during your unit testHave you ever had the following problem?<br />
You are debugging a unit test which has just inserted some records into your database. While the unit test is waiting on a breakpoint you want to see the result of the insert in the database. You start up SQL Query Analyzer type 'select * from customers' and hit <f5>. What happens? If you are lucky you get to see the table as it was before you started the unit test, if you are unlucky your query just 'hangs'. Now why is that? </f5><br />
Anyone who understands a little bit about transactions knows this must be because the insert is done inside a transaction which has not yet been committed. Therefore the result of the insert is isolated from any other database process or a table lock might even prevent you from reading the table at all.<br />
When I ran into this (again) today I started thinking about it and found a solution which in fact is very simple. Before running your select * from customers you execute the command:<br />
<br /><br />
<span style="font-family: "Courier New", Courier, monospace;">SET TRAN ISOLATION LEVEL READ UNCOMMITTED</span><br />
<br /><br />
The trick is that by setting the isolation level to 'read uncommitted' you can read the data that was inserted by the unit test code even though there might be table locks and the changes might eventually even get rolled back (which is usually the case in a unit test).<br />
Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0tag:blogger.com,1999:blog-425679407385328620.post-84080200221752371182006-09-24T22:59:00.000+02:002015-08-28T23:04:58.163+02:00Keep your hands off my stack traces!When the first beta of the .Net framework was released one of the best features I thought was that the Exception.ToString() method shows you the stack trace from the place where the exception is thrown to where it is caught. Stack traces are your best friend when finding the cause of an unexpected exception. Back in the VB 6 time we spent a lot of effort harvesting this information ourselves.<br />
This is why I get really upset when someone screws up the stack trace information by doing something like the following.<br />
<br /><br />
<span style="font-family: "Courier New", Courier, monospace;">try <br />{<br /> // method call that might throw an exception at some deeper level<br /> some.Method();<br />}<br />catch (Exception ex)<br />{<br /> // some code to figure out what to do with the exception (maybe logging or whatever)<br /><br /> // hmm in this case we do not really handle this exception after all, lets re-throw<br /> throw ex;<br />}</span><br />
<br /><br />
What is wrong with this code? It is the 'ex' behind the throw. When you re-throw an exception this way the stack trace information in the Exception object is cleared and it will appear to who ever catches it at a higher level as if the exception originated from the location where it is re-thrown, thereby loosing valuable information about the location where the exception really occurred.<br />
Inside a catch block you are allowed to use <strong>trow;</strong> (without an exception). The <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfTheThrowStatement.asp?frame=true" target="_blank">C# reference</a> doesn't say very much about this, except that it is used when re-throwing the current exception object in a catch clause. Sounds like it is pretty much the same as when you do explicitly throw the exception you just caught as in the code example.<br />
There is however a big difference that is not directly clear from the documentation. When you use throw without an exception you are actually saying "lets pretend I never caught this exception". This causes the Exception to be thrown further up while preserving the whole stack trace from the original throw to the next catch up the call stack. <br />
Now pretty please, with sugar on top, use throw; instead of throw ex; inside a catch block, and leave my stack trace alone!Frank Bakkerhttp://www.blogger.com/profile/07296127749943237260noreply@blogger.com0