C# - Adding condition to func results in stack overflow exception

I have a func as part of specification class which sorts the given iqueryable

Func<IQueryable<T>, IOrderedQueryable<T>>? Sort { get; set; }

When i add more than one condition to the func like below , it results in stack overflow exception.

spec.OrderBy(sc => sc.Case.EndTime).OrderBy(sc => sc.Case.StartTime);

The OrderBy method is implemented like this

public ISpecification<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> property)
    {
        _ = Sort == null ? Sort = items => items.OrderBy(property) : Sort = items => Sort(items).ThenBy(property);
        return this;
    }

Chaining or using separate lines doesn't make a difference.

This problem gets resolved if I assign a new instance of the specification and set it's func, but i don't want to be assigning to a new instance everytime. Please suggest what am i missing here and how to reuse the same instance (if possible).

1 answer

  • answered 2022-05-07 06:25 Jon Skeet

    This is the problematic part:

    Sort = items => Sort(items)
    

    That's like writing a method that calls itself.

    What you want is to evaluate the existing Sort function, not "the result of the Sort property at the time of evaluation".

    I would rewrite the method like this:

    public ISpecification<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> property)
    {
        var existingSort = Sort;
        Sort = existingSort is null
            ? items => items.OrderBy(property)
            : items => existingSort(items).ThenBy(property);
        return this;
    }
    

    (I would also echo D-Shih's comment - this is a somewhat counter-intuitive approach, and counter to normal LINQ. Maybe you have some particular reason to go against LINQ's expectations of immutability and chaining, but it's definitely unusual.)

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum