Today I faced a nasty bug, a null pointer exception in a property databound to our WPF application. This had some nasty side effects, and for sure this part of the code didn’t had any unit test, too bad! For sure now it has.
The line of code was really simple
Values.Where(model => model.IsSelected).FirstOrDefault().Refresh();
I guess you see the issue! If not here is the MSDN documentation:
- public static TSource FirstOrDefault< TSource >(this [NotNull] IEnumerable<TSource> source)
- in class Enumerable
Returns the first element of a sequence, or a default value if the sequence contains no elements.
The IEnumerable<out T> to return the first element of.
The type of the elements of source.
default(TSource) if source is empty; otherwise, the first element in source.
source is null.
Yeah, FirstOrDefault might returns null, so if you chain a call to another method it just crash!
For sure we know that! We use this method for that purpose, but an error can happen that fast!
So I decided that I wanted to be protected by my tooling. So I went back to read the post “Introducing ReSharper 5.0: Structural Search and Replace”
After several trial and some help from Ilya (Thanks!) I finally found the correct way to express what I wanted. My goal was to find all code which uses FirstOrDefault() method followed by a call to another method. Exactly like my issue.
enumerable is an Expression of type System.Collections.IEnumerable or derived type
method is a identifier placeholder with an empty indentifier name regexp
I then verified that this error was found. And also luckily that this was the only error of that kind in our application.
Then I finally added it to the Resharper Pattern Catalog, to show a warning.
Now when ever I will type this stupid thing, I will have my preferred tool Resharper, telling me how stupid I am to even try this!
BY the way you might download a sample Pattern Catalog from this blog post “Sample SSR Pattern Catalog Available for Download”. There are some cool stuff in there and it might help writing your owns.