C#List vs IEnumerable 性能问题

嗨,假设这两种方法:

private List GetProviderForType(Type type) { List returnValue = new List(); foreach (KeyValuePair provider in _objectProviders) { if ((provider.Key.IsAssignableFrom(type) || type.IsAssignableFrom(provider.Key)) && provider.Value.SupportsType(type)) { returnValue.Add(provider.Value); } } return returnValue; } private IEnumerable GetProviderForType1(Type type) { foreach (KeyValuePair provider in _objectProviders) if ((provider.Key.IsAssignableFrom(type) || type.IsAssignableFrom(provider.Key)) && provider.Value.SupportsType(type)) yield return provider.Value; } 

哪一个更快? 当我看第一种方法时,我看到内存是为List分配的,我认为不需要它。 IEnumerable方法似乎对我来说更快。

例如,假设你打电话

 int a = GetProviderForType(myType).Count; int b = GetProviderForType1(myType).Count(); 

现在,另一个问题是,这两个之间是否有性能差异?

你怎么看?

在这种特殊情况下,使用IEnumerable表单会更有效,因为您需要知道计数。 如果您不需要,存储数据,调整缓冲区大小等没有意义。

如果由于任何原因需要再次使用结果, List表单将更有效。

请注意, Count()扩展方法和Count属性对List都是有效的,因为Count()的实现检查目标序列是否实现ICollection并使用Count属性(如果是)。

另一个应该高效的选项(尽管只是)只是调用带有委托的Count的重载:

 private int GetProviderCount(Type type) { return _objectProviders.Count(provider => (provider.Key.IsAssignableFrom(type) || type.IsAssignableFrom(provider.Key)) && provider.Value.SupportsType(type)); } 

这将避免WhereSelect子句引起的额外级别的间接。

(正如Marc所说,对于少量数据,性能差异无论如何都可能是微不足道的。)

对此类问题的准确答案可能会因许多因素而有所不同,并且可能会随着CLR的发展而进一步变化。 确保唯一的方法是测量它 – 并记住,如果与将出现的操作相比差异很小,那么您应该选择最可读,可维护的编写方式。

在这方面,您可能还想尝试:

 private IEnumerable GetProviderForType1(Type type) { return _objectProviders.Where(provider => provider.Key.IsAssignableFrom(type) || type.IsAssignableFrom(provider.Key)) && provider.Value.SupportsType(type)) .Select(p => p.Value); } 

如果要将结果“快照”到列表中,还可以通过返回IEnumerable然后使用ToList扩展方法为自己提供很大的灵活性。 如果需要多次检查,这将避免重复评估代码以生成列表。

这个问题的一个重要部分是“数据有多大”? 多少行……

对于少量数据,列表很好 – 分配足够大的列表需要花费的时间可以忽略不计,并且它不会多次resize(没有,如果你可以告诉它有多大提前)。

但是,这不能扩展到庞大的数据量; 您的提供商似乎不太可能支持数千个接口,因此我不会说有必要使用这个模型 – 但它不会造成太大的伤害。

当然,您也可以使用LINQ:

 return from provider in _objectProviders where provider.Key.IsAssignableFrom(type) ... select provider.Value; 

这也是封面下的递延yield法……

IEnumerable和IList之间的主要区别:

IEnumerable:实现MoveNext,重置,获取当前方法并返回一种IEnumerator来迭代记录。

IList:暴露IEnumerable接口以及它也是可以通过索引访问的非generics对象的集合,因此IEnumerable + ICollection(操作数据)和添加,删除,插入(在特定索引处)是实现的有用方法IList的。

在查看你的Code in My Opinion后,IEnumerable更有效,但是如果你想对数据进行一些操作,返回列表也很有用,如果你只想迭代数据,那么IEnumerable是更好的选择。