Weird enough that when weather does not invite one to go outdoors and I have some spare time to indulge myself, being on my own for some hours, I decided to relax and do some programming work. Weird as it is a task that takes most of my working week, but I still certainly enjoy some of it even outside working hours.
My original implementation relied on the generic constraint IComparable<T> that constrained its use to types that implemented that interface (such as Int32, DateTime,… amongst others) but after reviewing the aforementioned link in which the author (brilliantly) uses expressions to generate delegates at runtime to compare types I thought it was a good idea to extend my own Range to support types that do not implement that interface, but custom code can be provided or, most importantly, generated by the use of expressions.
I ended up creating a new GenericRange type that removed the constraint, but instead, received a Comparison<T> delegate to perform the comparisons. Challenge was generating an expression that represented a default Comparison<T> for the overloads that did not receive the delegate.
I do not claim to be an expression guru but I thought I understood the concepts pretty well. After all I had played a little with expressions for static reflection purposes.
But implementing a generic Comparison<T> is a bit more contrived as it was proven when I tried to do it by brute force (exploring the API with just ideas in my head). That was clear after my third trip to the balcony to think ;-)
If you are not smart enough to seek for help but two pages on Google-search-results-fu did not bring the light. So I need to be the light that will bring meaningful search results when someone feeds your-favorite-search-engine with “implement Comparision<T> using expressions”.
And if you are not smart enough, the net lets you down you have to take it like a man and revert to tooling.
And that is exactly what I did: use a debugger visualizer over an existing expression to reverse-engineer it. I used a couple of them:
With this army on my side, I created what I named a “template expression” that looks like:
And of course, the tests that prove that I was on the right track:
A touch of debugging, inspect the template and take a pretty snapshot to have an overview:
Complete the overview with the information provided by the default visualizer, which, in my opinion, is closer to code than the pretty one, a bit of cleaning the code and… voilá, an expression that generates a comparison for types that can be compared (even if they do not imlpement IComparable<T>) is born:
And of course, the test that proves I did not screw-up:
- expressions are harder to write that one firsts thinks
- expression code is verbose, use tabs wisely
- debugger visualizers are your best friends, and include their authors in your prayers
- one feels incredible smart by even this small accomplishment
Enjoy (and mildly criticize it) the code.