Search code examples
c#linqexpressionbuilder

How to avoid duplicate code in linq queries


I have the code which can be considered as repetetive:

private IEnumerable<decimal?> GetWidth(IEnumerable<Rectangle> rectangles) =>
    rectangles.Where(s => s.Width != null)
    .Select(s => s.Width);

private IEnumerable<decimal?> GetHeight(IEnumerable<Rectangle> rectangles) =>
    rectangles.Where(s => s.Height != null)
        .Select(s => s.Height);

private IEnumerable<decimal?> GetDiameter(IEnumerable<Rectangle> rectangles) =>
    rectangles.Where(s => s.Diameter != null)
    .Select(s => s.Diameter);

private IEnumerable<decimal?> GetWeight(IEnumerable<Rectangle> rectangles) =>
    rectangles.Where(s => s.Weight != null)
        .Select(s => s.Weight);
        

The only difference between these methods is just field names such as Width, Height, Diameter, Weight. Is it possible to replace these names with a string property name and create just one method without using any third party libraries?


Solution

  • You can create simple extension for that:

    public static class EnumerableExtensions
    {
        public static IEnumerable<TValue> ExtractValues<TEntity, TValue>(
            this IEnumerable<TEntity> items,
            Func<TEntity, TValue?>    selector)
        {
            return items.Where(i => selector(i) != null)
                .Select(i => selector(i)!);
        }
    }
    

    And use it like this:

    var heights   = items.ExtractValues(i => i.Height);
    var diameters = items.ExtractValues(i => i.Diameter);