假设我有这样的事情:
IEnumerable<T> result = BuildAList<T>()
// lots of LINQ operators
;
但也许BuildAList
代价很高,而且除非有人真正开始迭代result
,否则我不想打电话给它。有没有一种简单的,惯用的方法来做到这一点?
(我显然可以编写自己的IEnumerable<T>
课程,但我希望有一种方法可以与现有的操作员一起完成。)
答案 0 :(得分:4)
我担心目前没有标准方法可以做到这一点,所以你必须自己动手。它不能是扩展方法,所以应该是带有迭代器块的常规静态方法(使用yield return
)和类似于Lazy<T>
的工厂委托,这将确保所需的延迟执行。
这样的事情:
public static class Iterators
{
public static IEnumerable<T> Lazy<T>(Func<IEnumerable<T>> factory)
{
foreach (var item in factory())
yield return item;
}
}
使用如下:
var result = Iterators.Lazy(() => BuildAList<T>());
// lots of LINQ operators
;
编辑:上述实现的缺点是,每次执行返回的枚举时都会调用工厂方法。通过将实现与Lazy<T>
类:
public static class Iterators
{
public static IEnumerable<T> Lazy<T>(Func<IEnumerable<T>> factory)
{
return LazyIterator(new Lazy<IEnumerable<T>>(factory));
}
private static IEnumerable<T> LazyIterator<T>(Lazy<IEnumerable<T>> source)
{
foreach (var item in source.Value)
yield return item;
}
}
答案 1 :(得分:1)
使用此模型通用方法:
public virtual IList<T> GetList(Func<T, bool> where,
params Expression<Func<T, object>>[] navigationProperties)
{
List<T> list;
using (var context = new DbEntities())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
list = dbQuery
.AsNoTracking()
.Where(where)
.ToList<T>();
}
return list;
}
答案 2 :(得分:1)
你可以将结果变成一个惰性属性并让下游的东西引用它。
class MyClass<T>
{
IEnumerable<T> result;
IEnumerable<T> Result
{
get { return result ?? (result = BuildAList()); }
}
List<T> BuildAList()
{
//...
}
}