Burned by Ternary Operators
First let me say that I’m not a fan of ternary operators. I try to avoid them because I feel that an explicit if/else is much more readable. I do use them on occasion and this seemed like the perfect place for them.
I ran into a interesting problem while trying to get a Linq where clause to work with ternary operators. In hindsight the problem is pretty obvious, but it stumped me and one of my coworkers for a few minutes. It wasn’t until we solved the problem in a different way that I realized what I had initially missed.
First the setup:
var books = new List<Book>(); books.Add(new Book { Title = "To Kill a Mockingbird", Description = null }); books.Add(new Book { Title = "Catcher in the Rye", Description = null });
There where clause I was building was part of some basic search functionality. It would take a passed in value and check to see if the Title or the Description contained that value:
var qry = books.Where(u => u.Description == null ? false : u.Description.ToUpper().Contains(searchStr) || u.Title == null ? false : u.Title.ToUpper().Contains(searchStr) );
Attempts to search for the letter T were returning no results. Like I said, I struggled with it, called in a second set of eyes and they couldn’t see the problem. We then re-wrote where clause like this:
var qry = books.Where(u => (u.Description != null && u.Description.ToUpper().Contains(searchStr)) || (u.Title != null && u.Title.ToUpper().Contains(searchStr)) );
This returned 2 results as expected. After a bit of rumination I realized the problem was my lack of parentheses. I thought I had written this:
var qry = books.Where(u => (u.Description == null ? false : u.Description.ToUpper().Contains(searchStr)) || (u.Title == null ? false : u.Title.ToUpper().Contains(searchStr)) );
When I had essentially written this:
var qry = books.Where(u => u.Description == null ? false : ( u.Description.ToUpper().Contains(searchStr) || u.Title == null ? false : u.Title.ToUpper().Contains(searchStr) ) );
This was clearly just my misunderstanding of how ternary operators are interpreted, and I’m unlikely to ever forget this, but I’m also going to continue to avoid ternary operators wherever I can and encourage others to do the same.