I ran across a bug today that threw me for a few minutes. It reminded me it’s always good to get refreshers on the basics even when (maybe especially when) you’ve been doing it for years.
Here’s a boiled down version of the code that was misbehaving:
This code is from a tool that reads data from a data reader and outputs that data to a stream in a specific format for consumption by a third party. Most items are simply mapped from a field to a position in the stream but in some cases more complex formatting or parsing rules need to be applied. Lambda expressions provide a great solution for this scenario. We have a few generic field mapping classes that allow us to “plug in” specific formatting or parsing rules, while still reusing the base mapping classes. It works great and there are dozens of these that apply the formatting rules to the various record and field types.
BUT… this code returns null even when paymentDescription has the value of “76”! (What the?!) I’ve been doing this long enough not to immediately assume the compiler has somehow broken, but I have to admit it took me a minute or two get the idea of what was going on. Here’s a hint…if this code were written as a normal method it would look something like this:
If you don’t see it already, the problem is that the comparison between paymentDescription and the literal string “76” is a comparison between an object and string, so it’s asking if the two are the same spot in memory rather than if their content is the same. The solution is to cast paymentDescription (which we know is a string in this case) to a string then the comparison works as intended.
The lambda syntax hid some of the details that I now realize I use as touchstones in my mental debugging checklist. If I’d seen that paymentDescription was an object and not a string, I’d have hit on the problem right away (that’s my story and I’m sticking to it).
This little bug, illustrates something that I’ve noticed a lot lately. When C# was first designed, one of the driving principles was readability and avoiding the syntaxes and mechanisms that had caused problems for C, C++ and other C-based languages. It seems that principle has taken a lower priority in favor of delivering more powerful and modern language features. That’s probably a good or at least necessary thing, but it means that more care has to be taken to deal with the more nuanced and cryptic syntaxes. And I need to update my debugging checklist.