Search code examples
c#linq

Operator "||" not working properly in a lambda expression


In the code below the second part of the filter is being executed even when the first part already returns "true". I understand that the use of the "||" operator should not perform the second part of the validation if the first is true.

List<data> query = new List<data>();

        query.Add(new data { name = "John", surname= "Mazi" });
        query.Add(new data { name = "Joseph", surname= "Doe" });
        query.Add(new data { name = "Paul", surname= "Allen" });
        query.Add(new data { name = "John", surname = "Doe" });


        data filters = new data { name = "John", surname = "Doe" };


        List<data> data = query.Where(x => ((x.name.Trim().ToUpper() == filters.name.Trim().ToUpper()
                                                & x.surname.Trim().ToUpper() == filters.surname.Trim().ToUpper())
                                        ||
                                             (x.name.Trim().ToUpper().Contains(filters.name.Trim().ToUpper())
                                                | x.surname.Trim().ToUpper().Contains(filters.surname.Trim().ToUpper())))).ToList();

In the example above it should only return one item but it keeps returning three.


Solution

  • Your understanding of the or operator is correct, but you have to take into consideration, that your validation will be executed for every entry inside the list. With this in mind, if you go through the validation, you will see why in this case three datasets get returned. For readability and ease of use, i would split the validation into two in your case:

    List<data> data = query.Where(x => ((x.name.Trim().ToUpper() == filters.name.Trim().ToUpper()
                                                    & x.surname.Trim().ToUpper() == filters.surname.Trim().ToUpper()).ToList();
    //If no exact matches, get datasets where name/ surname is contained
    if(!data.Any())
    {
        data = query.Where(x => (x.name.Trim().ToUpper().Contains(filters.name.Trim().ToUpper())
                                                    || (x.surname.Trim().ToUpper().Contains(filters.surname.Trim().ToUpper())).ToList();
    }
    

    This would first try to return every exact match and if none, every dataset where the name or surname is contained.