16 Sep

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>