设计应用程序的常用方法是什么,它强烈依赖于C#
(LINQ
,IEnumerable
,IQueryable
,...)中的延迟评估?
现在我通常尝试使用yield return
和LINQ
查询使每个查询尽可能地懒惰,但在运行时这通常会导致“太懒”行为,当每个查询从它开始构建时,显然会导致严重的视觉性能下降。
我通常做的是将ToList()
投影操作符放在某处缓存数据,但我怀疑这种方法可能不正确。
从一开始就设计这类应用程序的适当/常用方法是什么?
答案 0 :(得分:4)
我发现将每个IEnumerable分类为三个类别之一很有用。
对于类别1,我倾向于在适当的时候保留具体类型,数组或IList等。 对于类别3,最好将本地保留在方法中,以避免难以发现的错误。 然后我们有类别2,并且在优化性能时,一如既往地测量以找到瓶颈。
答案 1 :(得分:2)
一些随意的想法 - 因为问题本身是松散定义的:
答案 2 :(得分:2)
相当广泛的问题,不幸的是你会听到很多:这取决于。延迟加载是很好的,直到它不是。
通常,如果您反复使用相同的IEnumerables,最好将它们缓存为列表。
但是很少有人能够让你的来电者知道这一点。也就是说,如果你从存储库或其他东西获得IEnumerables,最好让存储库完成它的工作。它可能会在内部将其缓存为列表,也可能每次都将其构建。如果你的呼叫者试图变得太聪明,他们可能会错过数据的变化等等。
答案 3 :(得分:2)
我建议在返回DTO之前在DAL中执行ToList
public IList<UserDTO> GetUsers()
{
using (var db = new DbContext())
{
return (from u in db.tblUsers
select new UserDTO()
{
Name = u.Name
}).ToList();
}
}
在上面的示例中,有在DbContext范围结束之前执行ToList()。
答案 4 :(得分:1)
我需要缓存某个特定的数据序列,在该序列上调用其中一个聚合运算符(ToList
,ToArray
等)。否则只需使用延迟评估。
围绕数据构建代码。什么数据是易变的,每次都需要重新提升?使用延迟评估并且不要缓存。什么数据是相对静态的,只需要拉一次?将数据缓存在内存中,这样就不会不必要地将其拉出来。
答案 5 :(得分:0)
延迟执行并使用.ToList()
缓存所有项目并非唯一选项。第三个选项是使用惰性列表缓存您正在迭代的项。
执行仍然延期,但所有项目只会产生一次。这是如何工作的一个例子:
public class LazyListTest
{
private int _count = 0;
public void Test()
{
var numbers = Enumerable.Range(1, 40);
var numbersQuery = numbers.Select(GetElement).ToLazyList(); // Cache lazy
var total = numbersQuery.Take(3)
.Concat(numbersQuery.Take(10))
.Concat(numbersQuery.Take(3))
.Sum();
Console.WriteLine(_count);
}
private int GetElement(int value)
{
_count++;
// Some slow stuff here...
return value * 100;
}
}
如果你运行Test()方法,那么_count
只有10.没有缓存,它将是16而且。ToList()
它将是40!