为什么有人会使用IEnumerable?

13 浏览
0 Comments

为什么有人会使用IEnumerable?

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

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

或者

IEnumerable 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个似乎是委托。 \"inner\"成员中没有\"Animal\"实例,而是\"Species\"实例,这对我来说非常奇怪。 \"outer\"成员包含\"Animal\"实例。我想两个委派确定哪些内容进入其中,哪些内容会出来?
  2. 我注意到如果我使用“Distinct”,\"inner\"包含6个项(这是不正确的,因为只有2个是Distinct),但\"outer\"包含正确的值。同样,可能是委派方法决定了这一点,但这比我对IEnumerable知道的还要多一点。
  3. 最重要的是,哪个选项在性能方面最好?

邪恶的List转换通过.ToList()

还是直接使用枚举器?

如果可以的话,请解释一下或提供一些解释IEnumerable使用的链接。

admin 更改状态以发布 2023年5月24日
0
0 Comments

这里有一篇非常好的文章来自Claudio Bernasconi的技术博客:何时使用IEnumerable, ICollection, IList和List

下面是一些基本方案和功能:

enter image description here
enter image description here

0
0 Comments

IEnumerable是描述行为的,而List是该行为的实现。当您使用 IEnumerable时,您会让编译器有机会推迟工作,可能会在此过程中进行优化。如果您使用 ToList(),则会强制编译器立即重新定义结果。

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

public IEnumerable AllSpotted()
{
    return from a in Zoo.Animals
           where a.coat.HasSpots == true
           select a;
}
public IEnumerable Feline(IEnumerable sample)
{
    return from a in sample
           where a.race.Family == "Felidae"
           select a;
}
public IEnumerable Canine(IEnumerable sample)
{
    return from a in sample
           where a.race.Family == "Canidae"
           select a;
}

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

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

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

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

List Leopards = Feline(AllSpotted()).ToList();
List Hyenas = Canine(AllSpotted()).ToList();

0