【发布时间】:2014-05-31 22:28:03
【问题描述】:
我经常发现自己在写这样的东西:
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);
【问题讨论】:
-
为什么要先投影再过滤?如果您担心投影中不必要的分配,您不能在使用
Select()进行投影之前先使用Where.(prop => prop.GetCustomAttribute<ColumnAttribute>() != null)进行过滤吗? -
@ChrisHardie 这也是我的第一个想法。然而,调用
prop.GetCustomAttribute两次可能比分配两次更糟糕。 (直觉,这里没有真实数据)
标签: c# linq linq-to-objects