小编典典

IEnumerable vs List - 使用什么?它们是如何工作的?

all

我对枚举器的工作方式和 LINQ 有一些疑问。考虑这两个简单的选择:

List<Animal> sel = (from animal in Animals 
                    join race in Species
                    on animal.SpeciesKey equals race.SpeciesKey
                    select animal).Distinct().ToList();

要么

IEnumerable<Animal> sel = (from animal in Animals 
                           join race in Species
                           on animal.SpeciesKey equals race.SpeciesKey
                           select animal).Distinct();

我更改了原始对象的名称,以便看起来像一个更通用的示例。查询本身并不重要。我想问的是:

foreach (Animal animal in sel) { /*do stuff*/ }
  1. 我注意到,如果我使用IEnumerable,当我调试和检查“sel”(在这种情况下是 IEnumerable)时,它有一些有趣的成员:“inner”、“outer”、“innerKeySelector”和“outerKeySelector”,最后两个出现成为代表。“内部”成员中没有“动物”实例,而是“物种”实例,这对我来说很奇怪。“外部”成员确实包含“动物”实例。我想这两个代表决定了哪些进,哪些出?

  2. 我注意到如果我使用“Distinct”,“inner”包含 6 个项目(这是不正确的,因为只有 2 个是 Distinct),但“outer”确实包含正确的值。同样,委托方法可能决定了这一点,但这比我对 IEnumerable 的了解要多一些。

  3. 最重要的是,这两个选项中哪一个在性能方面是最好的?

邪恶的列表转换通过.ToList()

或者直接使用枚举器?

如果可以的话,也请解释一下或抛出一些解释 IEnumerable 用法的链接。


阅读 127

收藏
2022-03-02

共1个答案

小编典典

IEnumerable描述行为,而 List 是该行为的实现。当你使用
IEnumerable,你让编译器有机会将工作推迟到以后,可能会在此过程中进行优化。如果您使用 ToList(),您会强制编译器立即具体化结果。

每当我“堆叠”LINQ 表达式时,我都会使用IEnumerable,因为只指定行为我就给 LINQ 一个推迟评估并可能优化程序的机会。还记得 LINQ
是如何在您枚举之前不生成查询数据库的 SQL 的吗?考虑一下:

public IEnumerable<Animals> AllSpotted()
{
    return from a in Zoo.Animals
           where a.coat.HasSpots == true
           select a;
}

public IEnumerable<Animals> Feline(IEnumerable<Animals> sample)
{
    return from a in sample
           where a.race.Family == "Felidae"
           select a;
}

public IEnumerable<Animals> Canine(IEnumerable<Animals> sample)
{
    return from a in sample
           where a.race.Family == "Canidae"
           select a;
}

现在您有了一个选择初始样本(“AllSpotted”)以及一些过滤器的方法。所以现在你可以这样做:

var Leopards = Feline(AllSpotted());
var Hyenas = Canine(AllSpotted());

那么使用 List over 更快IEnumerable吗?仅当您想防止查询被多次执行时。但总体来说更好吗?在上面,Leopards 和 Hyenas
分别被转换为 单个 SQL 查询 ,并且数据库只返回相关的行。但是如果我们从
中返回了一个列表AllSpotted(),那么它可能会运行得更慢,因为数据库返回的数据可能比实际需要的多得多,而且我们浪费了在客户端进行过滤的周期。

在程序中,将查询转换为列表可能会更好,直到最后,所以如果我要多次列举 Leopards 和 Hyenas,我会这样做:

List<Animals> Leopards = Feline(AllSpotted()).ToList();
List<Animals> Hyenas = Canine(AllSpotted()).ToList();
2022-03-02