一尘不染

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

c#

我对Enumerators和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的用法。


阅读 613

收藏
2020-05-19

共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查询 ,并且数据库仅返回相关的行。但是,如果我们从中返回了一个List
AllSpotted(),则它的运行速度可能会变慢,因为数据库返回的数据可能远远超过实际需要的数据,并且浪费了在客户端进行过滤的周期。

在程序中,最好将查询转换为列表直到最后,最好,因此,如果我要多次通过Leopards和Hyenas枚举,我可以这样做:

List<Animals> Leopards = Feline(AllSpotted()).ToList();
List<Animals> Hyenas = Canine(AllSpotted()).ToList();
2020-05-19