嗨,假设这两种方法:

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

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

例如,假设你打电话

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

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

您怎么看?

有帮助吗?

解决方案

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

如果您因任何原因需要再次使用结果, List&lt; T&gt; 表单会更有效。

请注意, Count()扩展方法和 Count 属性对于 List&lt; T&gt; 都是有效的< code> Count()检查目标序列是否实现 ICollection&lt; T&gt; ,如果是,则使用 Count 属性。

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

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

这将避免 Where Select 子句带来的额外级别的间接。

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

其他提示

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

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

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

如果你想要“快照”,你可以通过返回 IEnumerable&lt; T&gt; 然后使用 ToList 扩展方法给自己很大的灵活性。将结果放入列表中。如果需要多次检查,这将避免重复评估代码以生成列表。

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

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

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

当然,您也可以使用LINQ:

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

这也是隐藏的 yield 方法......

IEnumerable和IList之间的主要区别:

IEnumerable的: 实现MoveNext,重置,获取当前方法并返回一类IEnumerator以进行迭代     通过记录。

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top