我在 WebApi 中应该使用 IEnumerable 还是 List 作为参数?
我在 WebApi 中应该使用 IEnumerable 还是 List 作为参数?
我对枚举器和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*/ }
- 我注意到如果我使用
IEnumerable
,当我调试并检查“sel”时,在那种情况下“sel”是IEnumerable,它有一些有趣的成员:“内部”,“外部”,“innerKeySelector”和“outerKeySelector”,这最后2个看起来是委托。 “内部”成员不包含“Animal”实例,而是包含“Species”实例,这对我来说非常奇怪。 “外部”成员包含“Animal”实例。我假设两个委托决定了哪个进入它以及什么离开它? - 我注意到如果我使用“Distinct”,“inner”包含6个项(这是不正确的,因为只有2个是不同的),但“outer”确实包含正确的值。再次,可能委托方法决定了这一点,但这比我对IEnumerable所知道的更多一些。
- 最重要的是,哪一个选项在性能上最好?
邪恶的通过.ToList()
进行的List转换?
还是直接使用枚举器?
如果可以的话,请也解释一下IEnumerable的使用,或提供一些解释这种使用的链接。
这里有一篇非常好的文章,由Claudio Bernasconi的TechBlog撰写,链接如下:何时使用IEnumerable、ICollection、IList和List
以下是关于场景和功能的基本要点:
IEnumerable
描述了行为,而List是该行为的实现。当您使用 IEnumerable
时,您给编译器一个机会,推迟工作直到以后,可能会在过程中进行优化。如果您使用 ToList(),则会立即强制编译器实例化结果。
每当我“叠加”LINQ表达式时,我使用 IEnumerable
,因为仅指定 behavior,我给LINQ一个机会推迟评估并可能优化程序。记住,LINQ在枚举之前不生成查询数据库的SQL语句。考虑一下:
public IEnumerableAllSpotted() { 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超过一次,我会这样做:
ListLeopards = Feline(AllSpotted()).ToList(); List Hyenas = Canine(AllSpotted()).ToList();