A strange thing about Nullable Boolean type, And and Or in C#

I have a strange problem about the following codes:

!isActive.HasValue || (isActive.HasValue && x.IsActive == isActive.Value)

isActive is a bool? type, so if isActive is null, then I will get the following error:

Nullable object must have a value.

Any idea about that? Thanks for your help!

Update 1:

public static List<User> Select(int userId, bool? isActive = null)
{
    var dl = DataLayer.GetDataContext();
    return dl.Users.Where(x => x.ID == userId
                && (!isActive.HasValue || (isActive.HasValue && x.IsActive == isActive.Value))).ToList();
}

This is the sample function I got this error. I know it is so strange! If I change like below, it will work:

!isActive.HasValue || (isActive.HasValue && x.IsActive == isActive)

I understand this error mean, but I don't understand why. It should work I think. So I call it strange thing!

Update 2:

  1. x.IsActive is bool type, not bool?. I am sure on it :)
  2. DataLayer.GetDataContext() is for Linq to SQL.

Is it possible it is because I am using SQL Server?

Thanks guys for your help so far.

Answers


Since it's Linq-to-SQL, then perhaps it's not short-circuiting or evaluating the expression parts in the proper order. I haven't used it, but from what I understand it reads the content of your lambda expressions and converts it to a close equivalent SQL statement; it does not actually execute it like C# code.

Even so, doing the check for each item seems like a bit much when the value is fixed. You could rewrite the method as such:

public static List<User> Select(int userId, bool? isActive = null)
{
    var dl = DataLayer.GetDataContext();
    var users = dl.Users.Where(x => x.ID == userID);

    if (!isActive.HasValue)
    {
        return users.ToList();
    }
    else
    {
        bool isActiveValue = isActive.Value;
        return users.Where(x => x.IsActive == isActiveValue).ToList();
    }
}

This way there's no additional constraints on the generated SQL query if they're not applicable. EDIT: Updated it so in addition, there are no nullable booleans being passed into your query whatsoever.


You have two different isActive values in your code, so it looks like you're missing the x on the second check:

!isActive.HasValue || (x.isActive.HasValue && (x.IsActive == isActive.Value))
                   ----^

I've also added parentheses around the equality check just to eliminate any confusion around the order or operations


Oh, it's because of the query builder in LINQ. There may be a way to execute your intention in one query (in fact it sounds like your updated code in the q does just that), but the straightforward thing to do is to split it into two queries since you know the value of isActive beforehand. That way you don't have to worry about what the query builder may or may not be doing.

For that matter you may as well just make this two separate functions entirely, just to make it harder for future maintainers to accidentally fall into the same trap:

public static List<User> Select(int userId)
{
    return DataLayer.GetDataContext().Users.Where(x => x.ID == userId).ToList();
}

public static List<User> Select(int userId, bool isActive)
{
    return DataLayer.GetDataContext().Users.Where(x => x.ID == userId && x.IsActive == isActive).ToList();
}

Need Your Help

Get data from RowCommand

c# asp.net gridview rowcommand

I have a grid which shows product version's and have a few link buttons like edit, delete, preview etc.

Get current cursor position in a texbox

javascript firefox textbox cursor

I don't know how to get the current cursor position for Firefox and Chrome. The following is the code which I am using,

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.