web-dev-qa-db-ja.com

Linq Select Where

私はよく次のようなことを書いています。

var fields = _type.GetProperties()
            .Select(prop => new { Prop = prop, Attrib = prop.GetCustomAttribute<ColumnAttribute>() })
            .Where(t => t.Attrib != null)
            .ToList();

私が気になっているのは、where句が失敗した場合に不必要にオブジェクトを作成していることです。確かにオーバーヘッドは小さいですが、単にループしたり、もっと苦痛をしたりした場合と同じように、割り当てを保存したいと思います。

var fields = _type.GetProperties()
        .Select(prop =>
        {
            var attrib = prop.GetCustomAttribute<ColumnAttribute>();

            return attrib == null ? null : new {Prop = prop, Attrib = attrib};
        })
        .Where(t => t != null);

私が見逃しているより良いパターン/拡張方法はありますか?それとも、LINQがその最適化を隠蔽して行う可能性はありますか?

大変感謝いたします!

更新:

私はこのようなものが私が意味していることだと思います、しかし私は同等のものがすでに存在することを期待していて、私はただ不十分に検索しています:

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);
7
Gene

実行しているクエリの種類については、実際に回避することはできません。あなたwillその属性をどこかに置く場所が欲しい。別のメソッドで非表示にする場合でも、結果オブジェクトを操作する場合でも、実行する必要があります。それについて心配するのは逆効果でしょう。しかし、読みやすくする方法はいくつかあります。

クエリ構文でクエリを書き直した場合、それが行われているという事実を隠すことができます

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

ただし、このためには、おそらくジェネレーターにパッケージ化します。 need LINQの観点から書く必要はありません。そうしようとすると、自分自身を真剣に制限することになります。

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);
    }
}

クエリは次のようになります。

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