Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning empty linq expression

Tags:

c#

linq

I have a WhereFilter property in a base class which is as follows:

public virtual Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return null; }
}

When it is overridden I want to return something else instead of null so I can use predicatebuilder extension And (from LinqKit) so I can write my code as follows:

public override Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return base.WhereFilter.And(x => x.CustomerID == 1); }
}

But this gives error as WhereFilter is null (Object reference not set to an instance of an object).

Currently I am writing as:

public override Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return x => x.CustomerID == 1; }
}

So when there is another child class overriding this, the base class property will be lost.

Any way to resolve this? In sql what I did was use a dummy where 1=1 thingy, can this be done similarly here in linq?

like image 726
Umair Avatar asked Sep 03 '13 13:09

Umair


3 Answers

LINQ's equivalent of the SQL's 1=1 "thingy" is a predicate that always returns true:

x => true

Change your default method as follows:

public virtual Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return x=>true; }
}
like image 75
Sergey Kalinichenko Avatar answered Oct 13 '22 10:10

Sergey Kalinichenko


You could simply check whether the inherited property returns null:

public override Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get {
        var baseResult = base.WhereFilter;
        if (baseResult == null) {
            return x => x.CustomerID == 1;
        } else {
            return base.WhereFilter.And(x => x.CustomerID == 1);
        }
    }
}

IMO this will be more readable than seemingly pointless dummy values that will make you (or anyone else working with the code) wonder at a later time what that was there fore. (And it will probably even result in a tiny bit less of overhead when running.)

If you insist on using less lines, you can shorten down the if-else expression by using the ?: operator.


EDIT: Thinking about this a little further, you could see it as a drawback that everyone overriding that property will have to write so much code, which may introduce errors. But then, it is a questionable design choice to rely on overriding methods not containing any such errors when calling the inherited code, as with the model you proposed, overriders might just as well return only their new predicate without calling And.

A cleaner design, IMO, would make the virtual property protected, and have it return only the new predicate (or null). The publicly accessible (and non-virtual) property would then be responsible for retrieving any predicates of the current and any superclasses, and combining them with And if there is more than one.

like image 5
O. R. Mapper Avatar answered Oct 13 '22 08:10

O. R. Mapper


You can do following:

    public virtual Expression<Func<CustomerCustomerType, bool>> WhereFilter    
    {
        get { return customerCustomerType => true; }
    }

which is an expression that always returns true.

like image 2
Piotr Stapp Avatar answered Oct 13 '22 10:10

Piotr Stapp