IEnumerable的VS列表 - 怎么使用?他们如何工作? [英] IEnumerable vs List - What to Use? How do they work?

查看:94
本文介绍了IEnumerable的VS列表 - 怎么使用?他们如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有超过普查员如何工作,以及LINQ有些疑惑。考虑这两个简单的选择:

 列表<动物> SEL =(从动物的动物
                    参加比赛物种
                    在animal.SpeciesKey等于race.SpeciesKey
                    选择动物).Distinct()了ToList()。

 的IEnumerable<动物> SEL =(从动物的动物
                           参加比赛物种
                           在animal.SpeciesKey等于race.SpeciesKey
                           选择动物).Distinct();

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

 的foreach(SEL中的兽兽){/ *做的东西* /}


  1. 我注意到,如果我使用的IEnumerable ,当我调试和检查SEL,在这种情况下,是IEnumerable的,它有一些有趣的成员: 内,外,innerKeySelector和outerKeySelector,这些过去2似乎代表。 内部成员没有在其动物的实例,而是种的情况下,这是很奇怪的我。 外的成员的确包含动物的实例。我presume这两个代表确定它出现在什么出去呢?


  2. 我注意到,如果我用另类,内部包含6个项目(这是不正确的只有2个是不同的),但外确实包含正确的值。再次,可能是委托方法确定此但这是多一点,比我知道的IEnumerable


  3. 更​​重要的是,两个选项哪个是最好的性能代价?


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

或许直接使用枚举?

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


解决方案

的IEnumerable 描述的行为,而名单是该行为的实现。当您使用的IEnumerable ,你给编译器有机会推迟工作,直到后来,可能是沿途的优化。如果你使用了ToList()您强制编译器具体化的结果的时候了。

每当我堆积LINQ前pressions,我用的IEnumerable ,因为只有指定的行为,我给LINQ有机会推迟评估,并可能优化方案。记住LINQ怎么不生成SQL,直到你枚举它来查询数据库?试想一下:

 公开的IEnumerable<动物> AllSpotted()
{
    从在Zoo.Animals返回
           其中,a.coat.HasSpots ==真
           选择一个;
}公共IEnumerable的<动物>猫(IEnumerable的<动物>样品)
{
    从样品返回
           其中,a.race.Family ==猫科动物
           选择一个;
}公共IEnumerable的<动物>犬(IEnumerable的<动物>样品)
{
    从样品返回
           其中,a.race.Family ==犬科
           选择一个;
}

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

  VAR豹猫=(AllSpotted());
变种鬣狗=犬(AllSpotted());

因此​​,它是快了的IEnumerable 使用List?只有当你想prevent被执行多次的查询。但它是更好的整体?在上面,豹子和鬣狗顺利拿到转化成的单个的SQL查询每个的,并且数据库仅返回相关的行。但是,如果我们从 AllSpotted(),那么它可能运行慢,因为该数据库可以返回更多的数据比实际需要的,我们浪费的周期做过滤返回列表在客户端

在一个程序中,它可能是更好推迟查询转换为一个列表,直到最后一刻,所以如果我经历豹子和鬣狗列举不止一次,我会做到这一点:

 列表<动物>豹=猫(AllSpotted())了ToList();
清单<动物>鬣狗=犬(AllSpotted())了ToList();

I have some doubts over how Enumerators work, and LINQ. Consider these two simple selects:

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

or

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

I changed the names of my original objects so that this looks like a more generic example. The query itself is not that important. What I want to ask is this:

foreach (Animal animal in sel) { /*do stuff*/ }

  1. I noticed that if I use IEnumerable, when I debug and inspect "sel", which in that case is the IEnumerable, it has some interesting members: "inner", "outer", "innerKeySelector" and "outerKeySelector", these last 2 appear to be delegates. The "inner" member does not have "Animal" instances in it, but rather "Species" instances, which was very strange for me. The "outer" member does contain "Animal" instances. I presume that the two delegates determine which goes in and what goes out of it?

  2. I noticed that if I use "Distinct", the "inner" contains 6 items (this is incorrect as only 2 are Distinct), but the "outer" does contain the correct values. Again, probably the delegated methods determine this but this is a bit more than I know about IEnumerable.

  3. Most importantly, which of the two options is the best performance-wise?

The evil List conversion via .ToList()?

Or maybe using the enumerator directly?

If you can, please also explain a bit or throw some links that explain this use of IEnumerable.

解决方案

IEnumerable describes behavior, while List is an implementation of that behavior. When you use IEnumerable, you give the compiler a chance to defer work until later, possibly optimizing along the way. If you use ToList() you force the compiler to reify the results right away.

Whenever I'm "stacking" LINQ expressions, I use IEnumerable, because by only specifying the behavior I give LINQ a chance to defer evaluation and possibly optimize the program. Remember how LINQ doesn't generate the SQL to query the database until you enumerate it? Consider this:

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;
}

Now you have a method that selects an initial sample ("AllSpotted"), plus some filters. So now you can do this:

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

So is it faster to use List over IEnumerable? Only if you want to prevent a query from being executed more than once. But is it better overall? Well in the above, Leopards and Hyenas get converted into single SQL queries each, and the database only returns the rows that are relevant. But if we had returned a List from AllSpotted(), then it may run slower because the database could return far more data than is actually needed, and we waste cycles doing the filtering in the client.

In a program, it may be better to defer converting your query to a list until the very end, so if I'm going to enumerate through Leopards and Hyenas more than once, I'd do this:

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

这篇关于IEnumerable的VS列表 - 怎么使用?他们如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆