Linq Select Where

c#, linq, linq-to-objects

Solution

For the type of query you're performing, you can't really get around it. You will want to have a place to put that attribute somewhere. Whether you hide it in a separate method or operate on your result object, it has to be done. It would be counter productive to worry about it. But there are ways you can make it more readable.

If you rewrote your query in the query syntax, you can hide the fact that it is being done

var fields =
    from prop in _type.GetProperties()
    let attr = prop.GetCustomAttribute<ColumnAttribute>()
    where attr != null
    select new
    {
        Prop = prop,
        Attrib = attr,
    };

For this however, I would probably package it up in a generator. It doesn't need to be written in terms of LINQ, you'd be seriously limiting yourself if you try to.

public static IEnumerable<TResult> SelectWhere<TSource, TValue, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, TValue> valueSelector,
        Func<TSource, TValue, bool> predicate,
        Func<TSource, TValue, TResult> resultSelector)
{
    foreach (var item in source)
    {
        var value = valueSelector(item);
        if (predicate(item, value))
            yield return resultSelector(item, value);
    }
}

Your query becomes this:

var fields = _type.GetProperties()
    .SelectWhere(
        p => p.GetCustomAttribute<ColumnAttribute>(),
        (p, a) => a != null,
        (p, a) => new { Prop = p, Attrib = a }
    )
    .ToList();

Problem

I often find myself writing something like this: ``` var fields = _type.GetProperties() .Select(prop => new { Prop = prop, Attrib = prop.GetCustomAttribute<ColumnAttribute>() }) .Where(t => t.Attrib != null) .ToList(); ``` Where I'm bothered is that I'm unnecessarily creating objects in the cases where the where clause fails. Granted the overhead is small, but I'd still prefer to save the allocation, as I would if I were simply looping over it or did the more painful: ``` var fields = _type.GetProperties() .Select(prop => { var attrib = prop.GetCustomAttribute<ColumnAttribute>(); return attrib == null ? null : new {Prop = prop, Attrib = attrib}; }) .Where(t => t != null); ``` Is there a better pattern/extension method I'm missing? Or is it possible that LINQ could make that optimization under the covers? Much appreciated! Update: I guess something like this is what I mean, but I'm expecting something equivalent already exists and I'm just searching poorly: ``` public static IEnumerable<TResult> SelectWhereNotNull<TSource, TValue, TResult>(this IEnumerable<TSource> source, Func<TSource, TValue> valueSelector, Func<TSource, TValue, TResult> selector) where TValue:class where TResult:class { return source .Select(s => { var val = valueSelector(s); if (val == null) { return null; } return selector(s, val); }) .Where(r => r != null); } var fields = _type.GetProperties() .SelectWhereNotNull(prop => prop.GetCustomAttribute<ColumnAttribute>(), Tuple.Create); ```

Original source