Book Review: Building Interactive Queries with LINQPad

Any new technical book has the challenge of adding value above and beyond what’s available for free on the web.  A new book on LINQPad has the additional challenge of adding value above and beyond the wealth of samples already included with LINQPad, including code samples from two LINQPad-enabled books.  So when I received my review copy of Building Interactive Queries with LINQPad, I was very curious to see what the author (Sebastien Finot) could accomplish in 126 pages.

Even as someone who has used LINQPad enough in the past few years to present on it on front of a .NET user group, I learned new things about the tool I hadn’t known before (such as the ability to interact with the console and CSS customization of the application’s look-and-feel).  The book might have been more accurately titled “Building Interactive Queries with LINQ and LINQPad”, as the book provided good examples of a wide variety for LINQs query operators.  Finot also mentioned the performance implications of ToList()–a very useful mention depending on the size of collection you might be dealing with in your queries.  All the code samples in the book are available for download as well.

The book missed some opportunities to add value for readers.  Fuller treatment of the NuGet dependency management capabilities in the paid versions of LINQPad would have been helpful in deciding if the feature was worth paying for.  Finot also mentioned the existence of LINQ to Twitter and LINQ to JSON APIs but didn’t link to the projects in the book.  More examples of using LINQ to parse and manipulate JSON (instead of XML) would have improved the book significantly, given the increased usage of JSON in .NET development these days.  Unfortunately, the code samples didn’t include databases, which would have enabled the author to go above and beyond the fairly standard Northwind database examples.  A custom OData feed for use in explaining the ability of LINQPad to query those data sources would have been a great help as well (given the rather tenuous availability of the sample services at

Building Interactive Queries with LINQPad is the only book I’ve seen dealing specifically with LINQPad.  If you use LINQPad on a regular basis (or plan to), the e-book is worth purchasing.  For an in-depth treatment of LINQ, you’ll have to look elsewhere.

Disclosure: I received the e-book free of charge from the publisher for the purpose of providing this review.

LINQ Aggregate for Comma-Separated Lists of Values

A couple of days ago, while pairing with my colleague Alexei on bug fixes to a new feature, we came across a bit of code that attempted to take an integer array and construct a string with a comma-delimited list of the numbers from it. The existing code didn’t quite work, so we wrote a basic for-each loop and used ReSharper to see what LINQ alternative it might construct. Here’s what ReSharper came up with:

int[] numbers = new[] {1, 5, 8, 26, 35, 42};
var result = numbers.Aggregate("", (current, item) => current + item.ToString() + ",");

Before ReSharper served this up, I wasn’t familiar with the Aggregate operator. When I checked out 101 LINQ Samples for it, the vast majority of the examples used numbers.

Filtering Heterogeneous Arrays in .NET

One of the bugs I was recently asked to fix for an application required me to determine whether or not to display one of the members of a list.  This proved somewhat challenging since the lists in question were heterogeneous (two difference subtypes of an abstract base class).  It turned out that LINQ provides a nice solution to this sort of problem in the form of the OfType<T> method.

Given an IEnumerable collection with elements of multiple types, calling OfType<T> on the collection where T is the desired type will return a collection containing only elements of type T.  Before learning about OfType<T>, I’d been using the Cast<T> method.  This was fine as long as all the collection elements were of the type T I wanted.  The moment this wasn’t the case, my LINQ query threw a cast exception.  OfType<T> seems to work similarly to the “as” operator in C#, in that it doesn’t complain if a list element isn’t type T–it simply excludes it from the returned collection.

Implementing Mouse Hover in WPF

We’ve spent the past couple of weeks at work giving ourselves a crash course in Windows Presentation Foundation (WPF) and LINQ.  I’m working on a code example that will switch the datatemplate in a list item when the mouse hovers over it.  Unfortunately, WPF has no MouseHover event like Windows Forms does.  The usual googling didn’t cough up a ready-made answer.  Some hacking on one example did reveal a half-answer (not ideal, but at least a start).

First, I set the ToolTip property of the element I used to organize my data (in this case, a StackPanel).  Next, I added a ToolTipOpening event for the StackPanel.  Here’s the code for StackPanel_ToolTipOpening:

private void StackPanel_ToolTipOpening(object sender, ToolTipEventArgs e)
e.Handled = true;
ContentPresenter presenter = (ContentPresenter)(((Border)((StackPanel)e.Source).Parent).TemplatedParent);
presenter.ContentTemplate = this.FindResource("Template2") as DataTemplate;

The result: instead of a tooltip displaying when you hover over a listbox row, the standard datatemplate is replaced with an expanded one that displays more information.  This approach definitely has flaws.  Beyond being a hack, there’s no way to set how long you can hover before the templates switch.

Switching from an expanded datatemplate back to a standard one involved a bit less work.  I added a MouseLeave event to the expanded template.  Here’s the code for the event:

private void StackPanel_MouseLeave(object sender, MouseEventArgs e)
ContentPresenter presenter = (ContentPresenter)(((Border)((StackPanel)e.Source).Parent).TemplatedParent);
presenter.ContentTemplate = this.FindResource("ScriptLine") as DataTemplate;

So once the mouse moves out of the listbox item with the expanded template, it switches back to the standard template.  Not an ideal solution, but it works.

This link started me down the path to finding a solution (for reference).