C#List <T> vs IEnumerable <T>性能问题

PaN*_*1Me 17 c# performance ienumerable list

嗨,假设这两种方法:

private List<IObjectProvider> GetProviderForType(Type type)
        {
            List<IObjectProvider> returnValue = new List<IObjectProvider>();

            foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
            {
                if ((provider.Key.IsAssignableFrom(type) ||
                    type.IsAssignableFrom(provider.Key)) &&
                    provider.Value.SupportsType(type))
                {
                    returnValue.Add(provider.Value);
                }
            }
            return returnValue;
        }

private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
        {
            foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
                if ((provider.Key.IsAssignableFrom(type) ||
                    type.IsAssignableFrom(provider.Key)) &&
                    provider.Value.SupportsType(type))

                    yield return provider.Value;              
        }
Run Code Online (Sandbox Code Playgroud)

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

例如,假设你打电话

int a = GetProviderForType(myType).Count;
int b = GetProviderForType1(myType).Count();
Run Code Online (Sandbox Code Playgroud)

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

你怎么看?

Jon*_*eet 33

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

如果您因任何原因需要再次使用结果,List<T>表单将更有效.

请注意,Count()扩展方法和Count属性都可以List<T>作为Count()检查的实现,以查看目标序列是否实现ICollection<T>并使用该Count属性(如果是).

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

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

这将避免Where和和Select条款引起的额外的间接性.

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

  • 你的所有答案都对我有所帮助,但我认为这个问题已经提到了所有内容,所以我接受了.谢谢! (2认同)

Mar*_*ell 6

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

对于少量数据,列表很好 - 分配足够大的列表所需的时间可以忽略不计,并且不会多次调整大小(如果您可以提前告诉它有多大,则不会调整大小)。

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

当然,您也可以使用 LINQ:

return from provider in _objectProviders
       where provider.Key.IsAssignableFrom(type) ...
       select provider.Value;
Run Code Online (Sandbox Code Playgroud)

这也是yield幕后的延迟方法......